{"data":{"skill":{"slug":"sickn33-nextjs-app-router-patterns","name":"nextjs-app-router-patterns","icon":"📦","repo":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/nextjs-app-router-patterns","status":"approved","author":"sickn33","authorVersion":null,"skillstoreRevision":2},"audit":{"id":"142ce293-020a-4fbd-a102-36a249db780f","skill_id":"0ac827bc-91c5-41a4-af7a-aebcd666bcd3","version":5,"content_hash":"v3:81e05e636292629114b76cbb3922fbe57672fc02:9cac63755b145c04656015145c145d9e5a3b541ff36440c18252d06166cee01e:8d73a7ceaf6ff5400edc430a46f61e682b24395577180527c7db6881634ecdcd:736b696c6c732f7369636b6e33332f6e6578746a732d6170702d726f757465722d7061747465726e73:f58f47b4fabfc2c7ae9915940ca6de7b","risk_level":"high","is_blocked":false,"safe_to_publish":false,"analysis_status":"ok","agent_auto_install_policy":"confirmation_required","manual_install_policy":"allowed","summary":"All 22 static findings are false positives caused by JavaScript template literals, Markdown code references, and ordinary Next.js examples. However, the playbook demonstrates database mutations without explicit schema validation or authorization, creating a high-risk pattern when copied into production.","remediation":[{"issue":"Mutation examples pass request or action data into database operations without demonstrating validation and authorization.","severity":"high","suggestion":"Validate inputs with a strict schema, select permitted fields, authenticate the caller, and enforce resource-level authorization before each database mutation."}],"risk_factor_evidence":[{"factor":"external_commands","evidence":[{"file":"resources/implementation-playbook.md","line_end":157,"line_start":136},{"file":"resources/implementation-playbook.md","line_end":244,"line_start":242},{"file":"SKILL.md","line_end":32,"line_start":32},{"file":"SKILL.md","line_end":36,"line_start":36}]},{"factor":"network","evidence":[{"file":"resources/implementation-playbook.md","line_end":75,"line_start":75},{"file":"resources/implementation-playbook.md","line_end":135,"line_start":135},{"file":"resources/implementation-playbook.md","line_end":501,"line_start":501},{"file":"resources/implementation-playbook.md","line_end":504,"line_start":504},{"file":"resources/implementation-playbook.md","line_end":507,"line_start":507},{"file":"resources/implementation-playbook.md","line_end":510,"line_start":510},{"file":"resources/implementation-playbook.md","line_end":75,"line_start":75}]},{"factor":"env_access","evidence":[{"file":"resources/implementation-playbook.md","line_end":136,"line_start":136},{"file":"resources/implementation-playbook.md","line_end":136,"line_start":136}]}],"critical_findings":[],"high_findings":[{"title":"Unvalidated and Unauthorized Database Mutation Patterns","locations":[{"file":"resources/implementation-playbook.md","line_end":424,"line_start":417},{"file":"resources/implementation-playbook.md","line_end":519,"line_start":513}],"confidence":0.96,"description":"The examples pass an entire request body or action data into database writes without showing schema validation, field allowlisting, authentication, or resource authorization.","review_kind":"security","source_category":"semantic","source_severity":"high","confidence_reasoning":"The POST handler directly supplies request.json() as create data, and the exported Server Action writes caller-supplied data without demonstrated controls. These are clear unsafe patterns when adopted."}],"medium_findings":[],"low_findings":[],"dangerous_patterns":[],"files_scanned":2,"total_lines":586,"audit_model":"codex","audited_at":"2026-08-04T15:53:59.311+00:00","created_at":"2026-08-05T01:36:07.668018+00:00","static_findings":[{"id":"external_commands:resources/implementation-playbook.md:136:ruby-shell-backtick-execution","file":"resources/implementation-playbook.md","pattern":"Ruby/shell backtick execution","snippet":"`${process.env.API_URL}/products?${new URLSearchParams(filters)}`,","category":"external_commands","line_end":157,"severity":"medium","line_start":136},{"id":"external_commands:resources/implementation-playbook.md:242:ruby-shell-backtick-execution","file":"resources/implementation-playbook.md","pattern":"Ruby/shell backtick execution","snippet":"redirect(`/orders/${order.id}/confirmation`)","category":"external_commands","line_end":244,"severity":"medium","line_start":242},{"id":"network:resources/implementation-playbook.md:75:fetch-api-call","file":"resources/implementation-playbook.md","pattern":"Fetch API call","snippet":"const res = await fetch('https://api.example.com/products', {","category":"network","line_end":75,"severity":"low","line_start":75},{"id":"network:resources/implementation-playbook.md:135:fetch-api-call","file":"resources/implementation-playbook.md","pattern":"Fetch API call","snippet":"const res = await fetch(","category":"network","line_end":135,"severity":"low","line_start":135},{"id":"network:resources/implementation-playbook.md:501:fetch-api-call","file":"resources/implementation-playbook.md","pattern":"Fetch API call","snippet":"fetch(url, { cache: 'no-store' })","category":"network","line_end":501,"severity":"low","line_start":501},{"id":"network:resources/implementation-playbook.md:504:fetch-api-call","file":"resources/implementation-playbook.md","pattern":"Fetch API call","snippet":"fetch(url, { cache: 'force-cache' })","category":"network","line_end":504,"severity":"low","line_start":504},{"id":"network:resources/implementation-playbook.md:507:fetch-api-call","file":"resources/implementation-playbook.md","pattern":"Fetch API call","snippet":"fetch(url, { next: { revalidate: 60 } })","category":"network","line_end":507,"severity":"low","line_start":507},{"id":"network:resources/implementation-playbook.md:510:fetch-api-call","file":"resources/implementation-playbook.md","pattern":"Fetch API call","snippet":"fetch(url, { next: { tags: ['products'] } })","category":"network","line_end":510,"severity":"low","line_start":510},{"id":"network:resources/implementation-playbook.md:75:hardcoded-url","file":"resources/implementation-playbook.md","pattern":"Hardcoded URL","snippet":"const res = await fetch('https://api.example.com/products', {","category":"network","line_end":75,"severity":"low","line_start":75},{"id":"env_access:resources/implementation-playbook.md:136:environment-variable-access-dot-notation","file":"resources/implementation-playbook.md","pattern":"Environment variable access (dot notation)","snippet":"`${process.env.API_URL}/products?${new URLSearchParams(filters)}`,","category":"env_access","line_end":136,"severity":"low","line_start":136},{"id":"env_access:resources/implementation-playbook.md:136:environment-variable-object","file":"resources/implementation-playbook.md","pattern":"Environment variable object","snippet":"`${process.env.API_URL}/products?${new URLSearchParams(filters)}`,","category":"env_access","line_end":136,"severity":"low","line_start":136},{"id":"sensitive:resources/implementation-playbook.md:136:environment-file-access","file":"resources/implementation-playbook.md","pattern":"Environment file access","snippet":"`${process.env.API_URL}/products?${new URLSearchParams(filters)}`,","category":"sensitive","line_end":136,"severity":"high","line_start":136},{"id":"blocker:resources/implementation-playbook.md:87:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"<ProductGrid products={products} />","category":"blocker","line_end":87,"severity":"low","line_start":87},{"id":"blocker:resources/implementation-playbook.md:148:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"<div className=\"grid grid-cols-3 gap-4\">","category":"blocker","line_end":148,"severity":"low","line_start":148},{"id":"blocker:resources/implementation-playbook.md:307:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"const { id } = await params","category":"blocker","line_end":307,"severity":"low","line_start":307},{"id":"blocker:resources/implementation-playbook.md:323:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"const { id } = await params","category":"blocker","line_end":323,"severity":"low","line_start":323},{"id":"blocker:resources/implementation-playbook.md:364:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"const { id } = await params","category":"blocker","line_end":364,"severity":"low","line_start":364},{"id":"blocker:resources/implementation-playbook.md:432:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"const { id } = await params","category":"blocker","line_end":432,"severity":"low","line_start":432},{"id":"blocker:resources/implementation-playbook.md:433:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"const product = await db.product.findUnique({ where: { id } })","category":"blocker","line_end":433,"severity":"low","line_start":433},{"id":"blocker:resources/implementation-playbook.md:517:system-reconnaissance","file":"resources/implementation-playbook.md","pattern":"System reconnaissance","snippet":"await db.product.update({ where: { id }, data })","category":"blocker","line_end":517,"severity":"low","line_start":517},{"id":"external_commands:SKILL.md:32:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- If detailed examples are required, open `resources/implementation-playbook.md`.","category":"external_commands","line_end":32,"severity":"medium","line_start":32},{"id":"external_commands:SKILL.md:36:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- `resources/implementation-playbook.md` for detailed patterns and examples.","category":"external_commands","line_end":36,"severity":"medium","line_start":36}],"finding_verdicts":[{"id":"external_commands:resources/implementation-playbook.md:136:ruby-shell-backtick-execution","reason":"The matched backticks delimit a JavaScript template literal used to construct a fetch URL. They do not invoke a shell or external command.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:resources/implementation-playbook.md:242:ruby-shell-backtick-execution","reason":"The backticks form a JavaScript template literal passed to Next.js redirect. No shell execution primitive or command is present.","verdict":"false_positive","confidence":0.99},{"id":"network:resources/implementation-playbook.md:75:fetch-api-call","reason":"This is a documented Next.js data-fetching example using the reserved example.com domain. The skill itself does not execute the request or transmit sensitive data.","verdict":"false_positive","confidence":0.98},{"id":"network:resources/implementation-playbook.md:135:fetch-api-call","reason":"The fetch appears in an instructional Server Component example and targets an application-configured API endpoint. No credential exfiltration or covert destination is shown.","verdict":"false_positive","confidence":0.96},{"id":"network:resources/implementation-playbook.md:501:fetch-api-call","reason":"This generic fetch expression only illustrates the no-store caching option. It is documentation, has no concrete destination, and is not executed by the skill.","verdict":"false_positive","confidence":0.99},{"id":"network:resources/implementation-playbook.md:504:fetch-api-call","reason":"This generic fetch expression demonstrates force-cache behavior. It neither defines a destination nor executes as part of the skill.","verdict":"false_positive","confidence":0.99},{"id":"network:resources/implementation-playbook.md:507:fetch-api-call","reason":"This generic fetch expression demonstrates time-based revalidation. It is a code example without a concrete endpoint or sensitive payload.","verdict":"false_positive","confidence":0.99},{"id":"network:resources/implementation-playbook.md:510:fetch-api-call","reason":"This generic fetch expression demonstrates cache tags. It is instructional text and does not perform a network request during skill use.","verdict":"false_positive","confidence":0.99},{"id":"network:resources/implementation-playbook.md:75:hardcoded-url","reason":"The hardcoded HTTPS URL uses example.com, a reserved documentation domain. It is a placeholder in a code sample, not an operational external service.","verdict":"false_positive","confidence":0.99},{"id":"env_access:resources/implementation-playbook.md:136:environment-variable-access-dot-notation","reason":"The example reads API_URL as normal application endpoint configuration. It does not expose the value to output or send a credential to an unrelated party.","verdict":"false_positive","confidence":0.97},{"id":"env_access:resources/implementation-playbook.md:136:environment-variable-object","reason":"This is the same documented process.env.API_URL configuration access. There is no environment enumeration, logging, or secret collection.","verdict":"false_positive","confidence":0.97},{"id":"sensitive:resources/implementation-playbook.md:136:environment-file-access","reason":"The code accesses one environment variable through process.env and never reads an environment file. API_URL is used as an endpoint, with no secret disclosure shown.","verdict":"false_positive","confidence":0.99},{"id":"blocker:resources/implementation-playbook.md:87:system-reconnaissance","reason":"ProductGrid is a React component name in rendered JSX. It performs no host, network, account, or environment reconnaissance.","verdict":"false_positive","confidence":1},{"id":"blocker:resources/implementation-playbook.md:148:system-reconnaissance","reason":"The matched text is a Tailwind CSS grid layout class. It has no system inspection behavior.","verdict":"false_positive","confidence":1},{"id":"blocker:resources/implementation-playbook.md:307:system-reconnaissance","reason":"The code extracts a route parameter named id from Next.js params. It does not inspect the host system or enumerate resources.","verdict":"false_positive","confidence":1},{"id":"blocker:resources/implementation-playbook.md:323:system-reconnaissance","reason":"The code extracts a photo route parameter for an instructional page example. It is unrelated to system reconnaissance.","verdict":"false_positive","confidence":1},{"id":"blocker:resources/implementation-playbook.md:364:system-reconnaissance","reason":"The code reads a product route parameter before loading page data. It does not gather machine or environment information.","verdict":"false_positive","confidence":1},{"id":"blocker:resources/implementation-playbook.md:432:system-reconnaissance","reason":"The code reads an id from an API route parameter. This ordinary request handling is not reconnaissance.","verdict":"false_positive","confidence":1},{"id":"blocker:resources/implementation-playbook.md:433:system-reconnaissance","reason":"The database lookup fetches one product by the route id in an example handler. It does not enumerate system information or perform discovery.","verdict":"false_positive","confidence":0.99},{"id":"blocker:resources/implementation-playbook.md:517:system-reconnaissance","reason":"The statement updates one product record by id. It is a mutation example, not a system reconnaissance operation.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:32:ruby-shell-backtick-execution","reason":"The backticks are Markdown inline-code delimiters around a relative resource path. No command is executed.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:36:ruby-shell-backtick-execution","reason":"The backticks format a resource filename as inline code in Markdown. The line contains no shell instruction or execution primitive.","verdict":"false_positive","confidence":1}],"semantic_findings":[{"title":"Unvalidated and Unauthorized Database Mutation Patterns","severity":"high","locations":[{"file":"resources/implementation-playbook.md","line_end":424,"line_start":417},{"file":"resources/implementation-playbook.md","line_end":519,"line_start":513}],"confidence":0.96,"description":"The examples pass an entire request body or action data into database writes without showing schema validation, field allowlisting, authentication, or resource authorization.","confidence_reasoning":"The POST handler directly supplies request.json() as create data, and the exported Server Action writes caller-supplied data without demonstrated controls. These are clear unsafe patterns when adopted."}],"subject_marketplace_commit_sha":"81e05e636292629114b76cbb3922fbe57672fc02","subject_content_hash":"9cac63755b145c04656015145c145d9e5a3b541ff36440c18252d06166cee01e","subject_tree_hash":"8d73a7ceaf6ff5400edc430a46f61e682b24395577180527c7db6881634ecdcd","subject_plugin_path":"skills/sickn33/nextjs-app-router-patterns","audit_payload_hash":"f58f47b4fabfc2c7ae9915940ca6de7b","confirmed_risk_level":"high","scanner_version":"3.0.0","policy_version":"skillstore-security-audit-policy-v1","subject":{"marketplaceCommitSha":"81e05e636292629114b76cbb3922fbe57672fc02","contentHash":"9cac63755b145c04656015145c145d9e5a3b541ff36440c18252d06166cee01e","treeHash":"8d73a7ceaf6ff5400edc430a46f61e682b24395577180527c7db6881634ecdcd","pluginPath":"skills/sickn33/nextjs-app-router-patterns","auditPayloadHash":"f58f47b4fabfc2c7ae9915940ca6de7b"},"scannerVersion":"3.0.0","policyVersion":"skillstore-security-audit-policy-v1"},"auditTranslation":null,"localization":{"requestedLocale":"en","contentLocale":"en","availableLocales":["en"],"fallbackToEnglish":false},"attestation":{"availability":"issued","url":"/api/skills/sickn33-nextjs-app-router-patterns/audits/5/attestation","status":"active"},"trust":{"publicState":"public","auditState":"complete","auditCurrentness":null,"confirmedRiskLevel":"high","confirmedFindingCount":1,"capabilityReviewCount":0,"needsReviewCount":0,"falsePositiveCount":0,"agentAutoInstallPolicy":"confirmation_required","manualInstallPolicy":"allowed","artifactSignatureState":"available","attestationState":"active","verificationState":"not_verified"},"isLatest":true}}