diff --git a/.security-review/suppressions.json b/.security-review/suppressions.json index ed6bb5f..e0e6398 100644 --- a/.security-review/suppressions.json +++ b/.security-review/suppressions.json @@ -1,20 +1,20 @@ { "suppressions": [ { - "id": "semgrep-detect-child-process-55", - "justification": "False positive. CDK local-bundling tryBundle(outputDir) in lib/door-unlock-stack.ts. execSync runs esbuild at cdk-synth time; outputDir is supplied by the CDK framework (staging temp dir) and the other path segments are repo-relative constants. No untrusted input, build-time only on a trusted host, never runs at request time. Verified proof-or-kill 2026-07-13. INFRA-105." + "id": "semgrep-detect-child-process-61", + "justification": "False positive. CDK local-bundling tryBundle(outputDir) in lib/door-unlock-stack.ts. execSync runs esbuild at cdk-synth time; outputDir is supplied by the CDK framework (staging temp dir) and the other path segments are repo-relative constants. No untrusted input, build-time only on a trusted host, never runs at request time. Verified proof-or-kill 2026-07-13. INFRA-105. Re-pointed from line 55 on 2026-07-23: fromStringParameterName cleanup shifted lines in lib/door-unlock-stack.ts; finding unchanged." }, { - "id": "semgrep-detect-child-process-84", - "justification": "False positive. Same as semgrep-detect-child-process-55: CDK local-bundling esbuild execSync with framework-supplied synth-time outputDir. Build-time only. INFRA-105." + "id": "semgrep-detect-child-process-90", + "justification": "False positive. Same as semgrep-detect-child-process-55: CDK local-bundling esbuild execSync with framework-supplied synth-time outputDir. Build-time only. INFRA-105. Re-pointed from line 84 on 2026-07-23: fromStringParameterName cleanup shifted lines in lib/door-unlock-stack.ts; finding unchanged." }, { - "id": "semgrep-detect-child-process-122", - "justification": "False positive. Same as semgrep-detect-child-process-55: CDK local-bundling esbuild execSync with framework-supplied synth-time outputDir. Build-time only. INFRA-105." + "id": "semgrep-detect-child-process-128", + "justification": "False positive. Same as semgrep-detect-child-process-55: CDK local-bundling esbuild execSync with framework-supplied synth-time outputDir. Build-time only. INFRA-105. Re-pointed from line 122 on 2026-07-23: fromStringParameterName cleanup shifted lines in lib/door-unlock-stack.ts; finding unchanged." }, { - "id": "semgrep-detect-child-process-202", - "justification": "False positive. Same as semgrep-detect-child-process-55: CDK local-bundling esbuild execSync with framework-supplied synth-time outputDir. Build-time only. INFRA-105." + "id": "semgrep-detect-child-process-210", + "justification": "False positive. Same as semgrep-detect-child-process-55: CDK local-bundling esbuild execSync with framework-supplied synth-time outputDir. Build-time only. INFRA-105. Re-pointed from line 202 on 2026-07-23: fromStringParameterName cleanup shifted lines in lib/door-unlock-stack.ts; finding unchanged." }, { "id": "checkov-CKV_AWS_111-234", @@ -22,7 +22,7 @@ }, { "id": "gitleaks-generic-api-key-5193", - "justification": "False positive. A provisioning-template token placeholder (the literal __DOOR_UNLOCK_TOKEN__) in Yealink T54W templates — not a secret. The real token was rotated in SSM (INFRA-105, param v3 2026-07-06) and the historical live token was removed by the git-filter-repo history scrub; only the placeholder remains." + "justification": "False positive. A provisioning-template token placeholder (the literal __DOOR_UNLOCK_TOKEN__) in Yealink T54W templates \u2014 not a secret. The real token was rotated in SSM (INFRA-105, param v3 2026-07-06) and the historical live token was removed by the git-filter-repo history scrub; only the placeholder remains." }, { "id": "gitleaks-generic-api-key-900", @@ -30,7 +30,7 @@ }, { "id": "gitleaks-generic-api-key-3097", - "justification": "False positive. A __DOOR_UNLOCK_TOKEN__ placeholder in a Yealink provisioning template (unlock linekey) — not a secret. Live token rotated in SSM 2026-07-06; history scrubbed via git-filter-repo (INFRA-105)." + "justification": "False positive. A __DOOR_UNLOCK_TOKEN__ placeholder in a Yealink provisioning template (unlock linekey) \u2014 not a secret. Live token rotated in SSM 2026-07-06; history scrubbed via git-filter-repo (INFRA-105)." } ] } diff --git a/lib/door-unlock-stack.ts b/lib/door-unlock-stack.ts index 269033a..e8b0efa 100644 --- a/lib/door-unlock-stack.ts +++ b/lib/door-unlock-stack.ts @@ -34,10 +34,16 @@ export class DoorUnlockStack extends cdk.Stack { { parameterName: "/seahaven/door-unlock/auth-token" } ); - const doorIdParam = ssm.StringParameter.fromStringParameterName( + // forceDynamicReference: the stack only needs the parameter for grantRead + // (ARN, built from the name); without it, fromStringParameterName injects + // an unreferenced AWS::SSM::Parameter::Value CloudFormation parameter. + const doorIdParam = ssm.StringParameter.fromStringParameterAttributes( this, "DoorId", - "/seahaven/door-unlock/door-id" + { + parameterName: "/seahaven/door-unlock/door-id", + forceDynamicReference: true, + } ); const unlockHandler = new lambda.Function(this, "UnlockHandler", { @@ -179,8 +185,10 @@ export class DoorUnlockStack extends cdk.Stack { ec2.Peer.ipv4("10.10.0.0/16"), ec2.Port.tcp(443), "HTTPS to phone LAN via VPN" ); - const phoneIpsParam = ssm.StringParameter.fromStringParameterName( - this, "PhoneIps", "/seahaven/door-unlock/phone-ips" + // forceDynamicReference for the same reason as DoorId above. + const phoneIpsParam = ssm.StringParameter.fromStringParameterAttributes( + this, "PhoneIps", + { parameterName: "/seahaven/door-unlock/phone-ips", forceDynamicReference: true } ); const phonePasswordSecret = secretsmanager.Secret.fromSecretNameV2(