Merge pull request #224 from ajmallesh/security/tighten-docker-env-isolation
Hardening local defaults
This commit is contained in:
@@ -677,6 +677,10 @@ Shannon is designed for legitimate security auditing purposes only.
|
|||||||
|
|
||||||
Windows Defender may flag files in `xben-benchmark-results/` or `deliverables/` as malware. These are false positives caused by exploit code in the reports. Add an exclusion for the Shannon directory in Windows Defender, or use Docker/WSL2.
|
Windows Defender may flag files in `xben-benchmark-results/` or `deliverables/` as malware. These are false positives caused by exploit code in the reports. Add an exclusion for the Shannon directory in Windows Defender, or use Docker/WSL2.
|
||||||
|
|
||||||
|
#### **7. Security Considerations**
|
||||||
|
|
||||||
|
Shannon Lite is designed for scanning repositories and applications you own or have explicit permission to test. Do not point it at untrusted or adversarial codebases. Like any AI-powered tool that reads source code, Shannon Lite is susceptible to prompt injection from content in the scanned repository.
|
||||||
|
|
||||||
|
|
||||||
## 📜 License
|
## 📜 License
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -3,8 +3,8 @@ services:
|
|||||||
image: temporalio/temporal:latest
|
image: temporalio/temporal:latest
|
||||||
command: ["server", "start-dev", "--db-filename", "/home/temporal/temporal.db", "--ip", "0.0.0.0"]
|
command: ["server", "start-dev", "--db-filename", "/home/temporal/temporal.db", "--ip", "0.0.0.0"]
|
||||||
ports:
|
ports:
|
||||||
- "7233:7233" # gRPC
|
- "127.0.0.1:7233:7233" # gRPC
|
||||||
- "8233:8233" # Web UI (built-in)
|
- "127.0.0.1:8233:8233" # Web UI (built-in)
|
||||||
volumes:
|
volumes:
|
||||||
- temporal-data:/home/temporal
|
- temporal-data:/home/temporal
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -47,7 +47,6 @@ services:
|
|||||||
- ./repos:/repos
|
- ./repos:/repos
|
||||||
- ${BENCHMARKS_BASE:-.}:/benchmarks
|
- ${BENCHMARKS_BASE:-.}:/benchmarks
|
||||||
shm_size: 2gb
|
shm_size: 2gb
|
||||||
ipc: host
|
|
||||||
security_opt:
|
security_opt:
|
||||||
- seccomp:unconfined
|
- seccomp:unconfined
|
||||||
|
|
||||||
@@ -63,7 +62,7 @@ services:
|
|||||||
envsubst < /config/router-config.json > /root/.claude-code-router/config.json &&
|
envsubst < /config/router-config.json > /root/.claude-code-router/config.json &&
|
||||||
ccr start"
|
ccr start"
|
||||||
ports:
|
ports:
|
||||||
- "3456:3456"
|
- "127.0.0.1:3456:3456"
|
||||||
volumes:
|
volumes:
|
||||||
- ./configs/router-config.json:/config/router-config.json:ro
|
- ./configs/router-config.json:/config/router-config.json:ro
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ function buildMcpServers(
|
|||||||
const isDocker = process.env.SHANNON_DOCKER === 'true';
|
const isDocker = process.env.SHANNON_DOCKER === 'true';
|
||||||
|
|
||||||
const mcpArgs: string[] = [
|
const mcpArgs: string[] = [
|
||||||
'@playwright/mcp@latest',
|
'@playwright/mcp@0.0.68',
|
||||||
'--isolated',
|
'--isolated',
|
||||||
'--user-data-dir', userDataDir,
|
'--user-data-dir', userDataDir,
|
||||||
];
|
];
|
||||||
@@ -92,13 +92,29 @@ function buildMcpServers(
|
|||||||
mcpArgs.push('--browser', 'chromium');
|
mcpArgs.push('--browser', 'chromium');
|
||||||
}
|
}
|
||||||
|
|
||||||
const envVars: Record<string, string> = Object.fromEntries(
|
// NOTE: Explicit allowlist — the Playwright MCP subprocess must not inherit
|
||||||
Object.entries({
|
// secrets (API keys, AWS tokens) from the parent process.
|
||||||
...process.env,
|
const MCP_ENV_ALLOWLIST = [
|
||||||
PLAYWRIGHT_HEADLESS: 'true',
|
'PATH', 'HOME', 'NODE_PATH', 'DISPLAY',
|
||||||
...(isDocker && { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' }),
|
'PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH',
|
||||||
}).filter((entry): entry is [string, string] => entry[1] !== undefined)
|
] as const;
|
||||||
);
|
|
||||||
|
const envVars: Record<string, string> = {
|
||||||
|
PLAYWRIGHT_HEADLESS: 'true',
|
||||||
|
...(isDocker && { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' }),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const key of MCP_ENV_ALLOWLIST) {
|
||||||
|
if (process.env[key]) {
|
||||||
|
envVars[key] = process.env[key]!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(process.env)) {
|
||||||
|
if (key.startsWith('XDG_') && value !== undefined) {
|
||||||
|
envVars[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mcpServers[playwrightMcpName] = {
|
mcpServers[playwrightMcpName] = {
|
||||||
type: 'stdio' as const,
|
type: 'stdio' as const,
|
||||||
|
|||||||
@@ -102,10 +102,19 @@ async function buildLoginInstructions(authentication: Authentication, logger: Ac
|
|||||||
// Pure function: Process @include() directives
|
// Pure function: Process @include() directives
|
||||||
async function processIncludes(content: string, baseDir: string): Promise<string> {
|
async function processIncludes(content: string, baseDir: string): Promise<string> {
|
||||||
const includeRegex = /@include\(([^)]+)\)/g;
|
const includeRegex = /@include\(([^)]+)\)/g;
|
||||||
// Use a Promise.all to handle all includes concurrently
|
const resolvedBase = path.resolve(baseDir);
|
||||||
|
|
||||||
const replacements: IncludeReplacement[] = await Promise.all(
|
const replacements: IncludeReplacement[] = await Promise.all(
|
||||||
Array.from(content.matchAll(includeRegex)).map(async (match) => {
|
Array.from(content.matchAll(includeRegex)).map(async (match) => {
|
||||||
const includePath = path.join(baseDir, match[1]!);
|
const includePath = path.resolve(baseDir, match[1]!);
|
||||||
|
if (!includePath.startsWith(resolvedBase + path.sep) && includePath !== resolvedBase) {
|
||||||
|
throw new PentestError(
|
||||||
|
`Path traversal detected in @include(): ${match[1]}`,
|
||||||
|
'prompt',
|
||||||
|
false,
|
||||||
|
{ includePath, baseDir: resolvedBase }
|
||||||
|
);
|
||||||
|
}
|
||||||
const sharedContent = await fs.readFile(includePath, 'utf8');
|
const sharedContent = await fs.readFile(includePath, 'utf8');
|
||||||
return {
|
return {
|
||||||
placeholder: match[0],
|
placeholder: match[0],
|
||||||
|
|||||||
Reference in New Issue
Block a user