#!/usr/bin/env node const assert = require("assert"); const fs = require("fs"); const path = require("path"); const repo = path.resolve(__dirname, ".."); function read(relativePath) { return fs.readFileSync(path.join(repo, relativePath), "utf8"); } function maybeRead(segments) { const fullPath = path.join(repo, ...segments); if (!fs.existsSync(fullPath)) return null; return fs.readFileSync(fullPath, "utf8"); } function expect(source, name, pattern) { assert.match(source, pattern, `missing hostile-input evidence: ${name}`); } function expectGate(script, gateName) { assert( script.includes("node scripts/hostile-input-contract-smoke.js"), `${gateName} must run hostile-input-contract-smoke.js` ); } const coreSource = read("crates/disasmer-core/src/source.rs"); const coreCapabilities = read("crates/disasmer-core/src/capability.rs"); const coordinatorService = read("crates/disasmer-coordinator/src/service.rs"); const artifactDownloadSmoke = read("scripts/artifact-download-smoke.js"); const operatorPanelSmoke = read("scripts/operator-panel-smoke.js"); const schedulerSmoke = read("scripts/scheduler-placement-smoke.js"); const sourcePreparationSmoke = read("scripts/source-preparation-smoke.js"); const publicAcceptance = read("scripts/acceptance-public.sh"); const publicSplit = read("scripts/verify-public-split.sh"); const privateAcceptance = read("scripts/acceptance-private.sh"); for (const [name, pattern] of [ ["source manifests validate shape", /pub fn validate_public_mvp\(&self\)[\s\S]*self\.validate_shape\(\)\?/], ["source manifests reject invalid digests", /SourceManifestError::InvalidDigest/], ["source manifests reject invalid custom providers", /SourceManifestError::InvalidProviderId/], ["source manifests reject control characters", /DescriptionControlCharacter/], ["source manifests reject coordinator checkout access", /CoordinatorCheckoutAccess/], ["source manifests reject default source-byte upload", /CoordinatorReceivesSourceBytes/], ]) { expect(coreSource, name, pattern); } for (const [name, pattern] of [ ["capability reports validate public shape", /pub fn validate_public_report\(&self\)/], ["capability reports validate architecture labels", /InvalidArchitecture/], ["capability reports validate OS labels", /InvalidOsLabel/], ["capability reports validate source providers", /InvalidSourceProvider/], ["source provider ids reject path traversal", /valid_source_provider_id/], ]) { expect(coreCapabilities, name, pattern); } for (const [name, pattern] of [ ["coordinator task log tails are bounded", /MAX_TASK_LOG_TAIL_BYTES: usize = 256 \* 1024/], ["coordinator validates reported stdout tails", /ReportTaskLog[\s\S]*validate_task_log_tail\("stdout_tail", &stdout_tail\)\?/], ["coordinator validates completed task stdout tails", /TaskCompleted[\s\S]*validate_task_log_tail\("stdout_tail", &stdout_tail\)\?/], ["coordinator rejects oversized log tail in unit coverage", /"x"\.repeat\(MAX_TASK_LOG_TAIL_BYTES \+ 1\)/], ]) { expect(coordinatorService, name, pattern); } for (const [name, pattern] of [ ["service rejects malformed node capability report", /fn service_rejects_malformed_node_capability_report\(\)/], ["capability report rejection leaves descriptors empty", /assert!\(service\.node_descriptors\.is_empty\(\)\)/], ["node capability report rejects cross-scope writes", /fn service_rejects_node_capability_report_outside_enrollment_scope\(\)/], ["task completion rejects cross-scope writes", /task completion outside node scope|outside/], ]) { expect(coordinatorService, name, pattern); } for (const [name, source, patterns] of [ [ "artifact download smoke", artifactDownloadSmoke, [ /const crossTenant = await send/, /const crossProject = await send/, /const guessed = await send/, /const crossActorOpen = await send/, /token is invalid/, /tenant mismatch/, /project mismatch/, ], ], [ "operator panel smoke", operatorPanelSmoke, [ /render_operator_panel/, /submit_panel_event/, /assert\(!JSON\.stringify\(panel\)\.includes\("[\s\S]*HostedResponse::Error/], ["tenant ids are validated", /fn tenant_id\(value: String\)[\s\S]*validate_identifier\("tenant", &value\)\?/], ["project ids are validated", /fn project_id\(value: String\)[\s\S]*validate_identifier\("project", &value\)\?/], ["user ids are validated", /fn user_id\(value: String\)[\s\S]*validate_identifier\("user", &value\)\?/], ["node ids are validated", /fn node_id\(value: String\)[\s\S]*validate_identifier\("node", &value\)\?/], ["process ids are validated", /fn process_id\(value: String\)[\s\S]*validate_identifier\("process", &value\)\?/], ["task ids are validated", /fn task_id\(value: String\)[\s\S]*validate_identifier\("task", &value\)\?/], ["artifact ids are validated", /fn artifact_id\(value: String\)[\s\S]*validate_identifier\("artifact", &value\)\?/], ["identifiers reject empty and control/path characters", /fn validate_identifier[\s\S]*trim\(\)\.is_empty\(\)[\s\S]*ch\.is_control\(\) \|\| ch == '\/' \|\| ch == '\\\\'/], ["OIDC and agent text fields are bounded", /fn validate_text[\s\S]*value\.len\(\) > max_bytes[\s\S]*contains unsupported characters/], ["tokens are bounded", /fn validate_token[\s\S]*value\.len\(\) > max_bytes[\s\S]*contains unsupported characters/], ["logs are bounded at service boundary", /fn validate_log[\s\S]*512 \* 1024/], ["debug requests validate process and task before inspection", /HostedRequest::DebugProcess[\s\S]*process_id\(process\)\?[\s\S]*task_id\(task\)\?[\s\S]*debug_process/], ["download requests validate artifact before action", /HostedRequest::DownloadAction[\s\S]*artifact_id\(artifact\)\?[\s\S]*download_action/], ["log completion requests validate task and stdout before recording", /HostedRequest::RecordUserNodeTaskCompletion[\s\S]*task_id\(task\)\?[\s\S]*validate_log\("task stdout", &stdout\)\?[\s\S]*record_user_node_task_completion/], ]) { expect(hostedService, name, pattern); } for (const [name, pattern] of [ ["running service rejects malformed JSON", /sendRaw\(addr, "\{not-json"\)/], ["running service rejects invalid tenant id", /tenant: " "/], ["running service rejects invalid project id", /project: "project\\nbad"/], ["running service rejects invalid task id", /task: "compile-linux\\nescape"/], ["running service rejects oversized logs", /stdout: "x"\.repeat\(256 \* 1024 \+ 1\)/], ["running service rejects cross-tenant debug", /const crossTenantDebug = await send/], ["running service rejects cross-tenant metadata", /const crossTenantMetadata = await send/], ["running service rejects cross-tenant download", /const crossTenantDownload = await send/], ["foreign snapshots do not reveal objects", /foreignSnapshot[\s\S]*snapshot\.nodes, \[\][\s\S]*snapshot\.logs, \[\][\s\S]*snapshot\.artifacts, \[\]/], ]) { expect(hostedSmoke, name, pattern); } } console.log("Hostile input contract smoke passed");