diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1584233..08905bc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,6 +3,9 @@ on: pull_request: branches: [main] +permissions: + contents: read + jobs: ci: uses: Sea-Haven-Industries/.github/.github/workflows/ci-typescript-cdk.yaml@fd60e4c9041784f666ac0fdefb9bec3c7fbf5143 # main diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 2cd8119..42002bb 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -1,6 +1,10 @@ name: Dependency Review on: pull_request: + +permissions: + contents: read + jobs: review: uses: Sea-Haven-Industries/.github/.github/workflows/callable-dependency-review.yaml@fd60e4c9041784f666ac0fdefb9bec3c7fbf5143 # main 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( diff --git a/package-lock.json b/package-lock.json index 2b42254..9b4daf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "seahaven-door-unlock", "version": "1.0.0", "dependencies": { - "aws-cdk-lib": "2.261.0", + "aws-cdk-lib": "2.262.0", "constructs": "^10.7.1" }, "bin": { @@ -38,9 +38,9 @@ "license": "Apache-2.0" }, "node_modules/@aws-cdk/cloud-assembly-schema": { - "version": "54.2.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-54.2.0.tgz", - "integrity": "sha512-u3lFXmiXSBozxGBmKTCVD/2mTDsaXzLZH3KYiIQKcB+zPldXOeE5TnooBgKV9ih2jVTo8ML0HpkhfAq2eiv0eQ==", + "version": "54.14.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-54.14.0.tgz", + "integrity": "sha512-JCZCzgp3SuXQVljaKqXnttHzcezEHt9Ag/YipK0XwUFD+Iz2T4jY7gUc3pA25Uq6pzY2n9DvO/nEU++dPXW4Rw==", "bundleDependencies": [ "jsonschema", "semver" @@ -48,7 +48,7 @@ "license": "Apache-2.0", "dependencies": { "jsonschema": "^1.5.0", - "semver": "^7.8.1" + "semver": "^7.8.5" }, "engines": { "node": ">= 18.0.0" @@ -63,7 +63,7 @@ } }, "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": { - "version": "7.8.1", + "version": "7.8.5", "inBundle": true, "license": "ISC", "bin": { @@ -1264,10 +1264,11 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.261.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.261.0.tgz", - "integrity": "sha512-e52e3Abjg0HkuRWlWwtSv5+ZiMW1rhCDdL9ff7lzWXInU8xdfLJpuoimfa0IJwjiNGyphppgg52Azx9M80OA0g==", + "version": "2.262.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.262.0.tgz", + "integrity": "sha512-6zRVoWRd8kQs9ZZ9xhERSm36W8uWS2vW3/g9Zx0xlhvRRiUwTc80bzfJkohKGdT/5AOW+wy6fSDvohavG94pcA==", "bundleDependencies": [ + "@aws/cloudformation-validate", "@balena/dockerignore", "@aws-cdk/cloud-assembly-api", "case", @@ -1284,17 +1285,18 @@ "dependencies": { "@aws-cdk/asset-awscli-v1": "2.2.282", "@aws-cdk/asset-node-proxy-agent-v6": "^2.1.2", - "@aws-cdk/cloud-assembly-api": "^2.2.5", - "@aws-cdk/cloud-assembly-schema": "^54.0.0", + "@aws-cdk/cloud-assembly-api": "^2.2.6", + "@aws-cdk/cloud-assembly-schema": "^54.11.0", + "@aws/cloudformation-validate": "1.5.0-beta", "@balena/dockerignore": "^1.0.2", "case": "1.6.3", - "fs-extra": "^11.3.5", + "fs-extra": "^11.3.6", "ignore": "^5.3.2", "jsonschema": "^1.5.0", "mime-types": "^2.1.35", "minimatch": "^10.2.5", "punycode": "^2.3.1", - "semver": "^7.8.1", + "semver": "^7.8.5", "yaml": "1.10.3" }, "engines": { @@ -1305,18 +1307,27 @@ } }, "node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api": { - "version": "2.2.5", + "version": "2.2.6", "inBundle": true, "license": "Apache-2.0", "dependencies": { "jsonschema": "^1.5.0", - "semver": "^7.8.0" + "semver": "^7.8.4" }, "engines": { "node": ">= 18.0.0" }, "peerDependencies": { - "@aws-cdk/cloud-assembly-schema": ">=53.28.0" + "@aws-cdk/cloud-assembly-schema": ">=54.5.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/@aws/cloudformation-validate": { + "version": "1.5.0-beta", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^22.15.0", + "npm": ">=10.5.0" } }, "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { @@ -1333,7 +1344,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/brace-expansion": { - "version": "5.0.6", + "version": "5.0.7", "inBundle": true, "license": "MIT", "dependencies": { @@ -1352,7 +1363,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/fs-extra": { - "version": "11.3.5", + "version": "11.3.6", "inBundle": true, "license": "MIT", "dependencies": { @@ -1438,7 +1449,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/semver": { - "version": "7.8.1", + "version": "7.8.5", "inBundle": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 561d5dc..183d2ef 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "typescript": "~7.0.2" }, "dependencies": { - "aws-cdk-lib": "2.261.0", + "aws-cdk-lib": "2.262.0", "constructs": "^10.7.1" } }