{"data":{"skill":{"slug":"zhanlincui-webapp-testing","name":"webapp-testing","icon":"📦","repo":"https://github.com/ZhanlinCui/Ultimate-Agent-Skills-Collection/tree/main/webapp-testing","status":"approved","author":"ZhanlinCui","authorVersion":null,"skillstoreRevision":null},"audit":{"id":"75e939c6-13de-4608-a881-dccb302fe0dc","skill_id":"3760fc52-a467-48d9-ac1d-1f7dda0de51f","version":3,"content_hash":"v2:88a205c7f635a966e31156313b590d59007c5caa:51b7349e77ec63b7744a6f63647e7566a0b4d2e301121cc10e8c2113af6556a2:2efbb482a1814eb59887db44e29fd0aa6ed71fa8f9ee3ac52cdb8cba6748ff54:1049d1a3461676009ecf50b57346ff56","risk_level":"high","is_blocked":false,"safe_to_publish":false,"analysis_status":"ok","agent_auto_install_policy":"confirmation_required","manual_install_policy":"allowed","summary":"Most static Markdown and localhost findings are false positives from documentation examples or local debugging artifacts. The helper script does execute user-supplied commands, including shell=True server commands, and the skill text discourages source review before execution.","remediation":[{"issue":"Server commands are launched with shell=True.","severity":"high","suggestion":"Accept server commands as argument arrays, add allowlisted presets, or require explicit confirmation before shell execution."},{"issue":"The skill tells agents not to read bundled script source before use.","severity":"high","suggestion":"Replace black-box guidance with advice to inspect helper behavior and run --help before executing trusted commands."},{"issue":"Examples use fixed output paths for screenshots and console logs.","severity":"medium","suggestion":"Make output paths configurable and document that generated artifacts may contain local application data."}],"risk_factor_evidence":[{"factor":"network","evidence":[{"file":"examples/console_logging.py","line_end":5,"line_start":5},{"file":"examples/element_discovery.py","line_end":10,"line_start":10},{"file":"SKILL.md","line_end":59,"line_start":59}]},{"factor":"filesystem","evidence":[{"file":"examples/console_logging.py","line_end":31,"line_start":31},{"file":"examples/element_discovery.py","line_end":37,"line_start":37},{"file":"examples/element_discovery.py","line_end":38,"line_start":38},{"file":"SKILL.md","line_end":69,"line_start":69}]},{"factor":"external_commands","evidence":[{"file":"scripts/with_server.py","line_end":88,"line_start":88},{"file":"scripts/with_server.py","line_end":69,"line_start":69},{"file":"SKILL.md","line_end":12,"line_start":12},{"file":"SKILL.md","line_end":14,"line_start":14},{"file":"SKILL.md","line_end":33,"line_start":18},{"file":"SKILL.md","line_end":37,"line_start":33},{"file":"SKILL.md","line_end":40,"line_start":37},{"file":"SKILL.md","line_end":42,"line_start":40},{"file":"SKILL.md","line_end":45,"line_start":42},{"file":"SKILL.md","line_end":50,"line_start":45},{"file":"SKILL.md","line_end":53,"line_start":50},{"file":"SKILL.md","line_end":63,"line_start":53},{"file":"SKILL.md","line_end":68,"line_start":63},{"file":"SKILL.md","line_end":72,"line_start":68},{"file":"SKILL.md","line_end":80,"line_start":72},{"file":"SKILL.md","line_end":81,"line_start":80},{"file":"SKILL.md","line_end":85,"line_start":81},{"file":"SKILL.md","line_end":85,"line_start":85},{"file":"SKILL.md","line_end":88,"line_start":86},{"file":"SKILL.md","line_end":88,"line_start":88},{"file":"SKILL.md","line_end":89,"line_start":89},{"file":"SKILL.md","line_end":95,"line_start":94},{"file":"SKILL.md","line_end":96,"line_start":95}]}],"critical_findings":[],"high_findings":[{"title":"Python subprocess.run","locations":[{"file":"scripts/with_server.py","line_end":88,"line_start":88}],"confidence":0.74,"description":"result = subprocess.run(args.command)","review_kind":"capability","source_category":"external_commands","source_severity":"high","confidence_reasoning":"The helper executes the trailing command supplied on the CLI. This is intended behavior, but it still enables arbitrary local command execution if unsafe arguments are provided."},{"title":"Python subprocess.Popen","locations":[{"file":"scripts/with_server.py","line_end":69,"line_start":69}],"confidence":0.9,"description":"process = subprocess.Popen(","review_kind":"capability","source_category":"external_commands","source_severity":"high","confidence_reasoning":"The helper starts user-supplied server commands with shell=True. That creates real shell command execution risk if untrusted command text reaches --server."},{"title":"Prompt Injection Attempt Detected","locations":[{"file":"SKILL.md","line_end":14,"line_start":14},{"file":"SKILL.md","line_end":85,"line_start":85}],"confidence":0.82,"description":"The skill says \"DO NOT read the source\" and promotes bundled scripts as black boxes before execution, which can suppress review of risky helper code.","review_kind":"security","source_category":"semantic","source_severity":"high","confidence_reasoning":"The wording directly instructs agents to avoid source inspection before running bundled scripts. The risk is confirmed by the helper using shell=True, but the text may be intended as context management rather than malicious evasion."}],"medium_findings":[{"title":"Ruby/shell backtick execution","locations":[{"file":"SKILL.md","line_end":42,"line_start":40}],"confidence":0.68,"description":"```bash","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The fenced bash example instructs agents to run the helper with an npm server command. It is legitimate usage, but still documents local external command execution."},{"title":"Ruby/shell backtick execution","locations":[{"file":"SKILL.md","line_end":50,"line_start":45}],"confidence":0.7,"description":"```bash","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The fenced bash example includes cd, python, npm, and multiple --server commands. It documents shell-based local server startup that requires trusted inputs."}],"low_findings":[],"dangerous_patterns":[],"files_scanned":5,"total_lines":310,"audit_model":"codex","audited_at":"2026-07-08T16:50:24.189+00:00","created_at":"2026-07-08T17:49:45.635108+00:00","static_findings":[{"id":"network:examples/console_logging.py:5:hardcoded-url","file":"examples/console_logging.py","pattern":"Hardcoded URL","snippet":"url = 'http://localhost:5173'  # Replace with your URL","category":"network","line_end":5,"severity":"low","line_start":5},{"id":"filesystem:examples/console_logging.py:31:python-file-write-append","file":"examples/console_logging.py","pattern":"Python file write/append","snippet":"with open('/mnt/user-data/outputs/console.log', 'w') as f:","category":"filesystem","line_end":31,"severity":"medium","line_start":31},{"id":"network:examples/element_discovery.py:10:hardcoded-url","file":"examples/element_discovery.py","pattern":"Hardcoded URL","snippet":"page.goto('http://localhost:5173')","category":"network","line_end":10,"severity":"low","line_start":10},{"id":"filesystem:examples/element_discovery.py:37:temp-directory-access","file":"examples/element_discovery.py","pattern":"Temp directory access","snippet":"page.screenshot(path='/tmp/page_discovery.png', full_page=True)","category":"filesystem","line_end":37,"severity":"medium","line_start":37},{"id":"filesystem:examples/element_discovery.py:38:temp-directory-access","file":"examples/element_discovery.py","pattern":"Temp directory access","snippet":"print(\"\\nScreenshot saved to /tmp/page_discovery.png\")","category":"filesystem","line_end":38,"severity":"medium","line_start":38},{"id":"external_commands:scripts/with_server.py:88:python-subprocess-run","file":"scripts/with_server.py","pattern":"Python subprocess.run","snippet":"result = subprocess.run(args.command)","category":"external_commands","line_end":88,"severity":"high","line_start":88},{"id":"external_commands:scripts/with_server.py:69:python-subprocess-popen","file":"scripts/with_server.py","pattern":"Python subprocess.Popen","snippet":"process = subprocess.Popen(","category":"external_commands","line_end":69,"severity":"high","line_start":69},{"id":"external_commands:SKILL.md:12:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- `scripts/with_server.py` - Manages server lifecycle (supports multiple servers)","category":"external_commands","line_end":12,"severity":"medium","line_start":12},{"id":"external_commands:SKILL.md:14:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"**Always run scripts with `--help` first** to see usage. DO NOT read the source until you try runnin","category":"external_commands","line_end":14,"severity":"medium","line_start":14},{"id":"external_commands:SKILL.md:18:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":33,"severity":"medium","line_start":18},{"id":"external_commands:SKILL.md:33:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":37,"severity":"medium","line_start":33},{"id":"external_commands:SKILL.md:37:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"To start a server, run `--help` first, then use the helper:","category":"external_commands","line_end":40,"severity":"medium","line_start":37},{"id":"external_commands:SKILL.md:40:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```bash","category":"external_commands","line_end":42,"severity":"medium","line_start":40},{"id":"external_commands:SKILL.md:42:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":45,"severity":"medium","line_start":42},{"id":"external_commands:SKILL.md:45:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```bash","category":"external_commands","line_end":50,"severity":"medium","line_start":45},{"id":"external_commands:SKILL.md:50:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":53,"severity":"medium","line_start":50},{"id":"external_commands:SKILL.md:53:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```python","category":"external_commands","line_end":63,"severity":"medium","line_start":53},{"id":"external_commands:SKILL.md:63:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":68,"severity":"medium","line_start":63},{"id":"external_commands:SKILL.md:68:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```python","category":"external_commands","line_end":72,"severity":"medium","line_start":68},{"id":"external_commands:SKILL.md:72:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":80,"severity":"medium","line_start":72},{"id":"external_commands:SKILL.md:80:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"❌ **Don't** inspect the DOM before waiting for `networkidle` on dynamic apps","category":"external_commands","line_end":81,"severity":"medium","line_start":80},{"id":"external_commands:SKILL.md:81:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"✅ **Do** wait for `page.wait_for_load_state('networkidle')` before inspection","category":"external_commands","line_end":85,"severity":"medium","line_start":81},{"id":"external_commands:SKILL.md:85:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **Use bundled scripts as black boxes** - To accomplish a task, consider whether one of the scripts","category":"external_commands","line_end":85,"severity":"medium","line_start":85},{"id":"external_commands:SKILL.md:86:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- Use `sync_playwright()` for synchronous scripts","category":"external_commands","line_end":88,"severity":"medium","line_start":86},{"id":"external_commands:SKILL.md:88:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- Use descriptive selectors: `text=`, `role=`, CSS selectors, or IDs","category":"external_commands","line_end":88,"severity":"medium","line_start":88},{"id":"external_commands:SKILL.md:89:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- Add appropriate waits: `page.wait_for_selector()` or `page.wait_for_timeout()`","category":"external_commands","line_end":89,"severity":"medium","line_start":89},{"id":"external_commands:SKILL.md:94:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- `element_discovery.py` - Discovering buttons, links, and inputs on a page","category":"external_commands","line_end":95,"severity":"medium","line_start":94},{"id":"external_commands:SKILL.md:95:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- `static_html_automation.py` - Using file:// URLs for local HTML","category":"external_commands","line_end":96,"severity":"medium","line_start":95},{"id":"network:SKILL.md:59:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"page.goto('http://localhost:5173') # Server already running and ready","category":"network","line_end":59,"severity":"low","line_start":59},{"id":"filesystem:SKILL.md:69:temp-directory-access","file":"SKILL.md","pattern":"Temp directory access","snippet":"page.screenshot(path='/tmp/inspect.png', full_page=True)","category":"filesystem","line_end":69,"severity":"medium","line_start":69}],"finding_verdicts":[{"id":"network:examples/console_logging.py:5:hardcoded-url","reason":"The URL points to localhost for a local development app. It does not contact an external service or transmit data off machine.","verdict":"false_positive","confidence":0.94},{"id":"filesystem:examples/console_logging.py:31:python-file-write-append","reason":"The example writes captured browser console messages to a visible output log path. This is expected test artifact creation, not hidden file modification.","verdict":"false_positive","confidence":0.83},{"id":"network:examples/element_discovery.py:10:hardcoded-url","reason":"The Playwright example navigates to localhost for local UI inspection. No external network endpoint or exfiltration behavior is present.","verdict":"false_positive","confidence":0.94},{"id":"filesystem:examples/element_discovery.py:37:temp-directory-access","reason":"The code saves a screenshot to /tmp as a local inspection artifact. It does not read sensitive files or write outside an obvious temporary path.","verdict":"false_positive","confidence":0.86},{"id":"filesystem:examples/element_discovery.py:38:temp-directory-access","reason":"This line only prints the temporary screenshot path. It performs no filesystem operation itself.","verdict":"false_positive","confidence":0.96},{"id":"external_commands:scripts/with_server.py:88:python-subprocess-run","reason":"The helper executes the trailing command supplied on the CLI. This is intended behavior, but it still enables arbitrary local command execution if unsafe arguments are provided.","verdict":"confirmed","severity":"high","confidence":0.74},{"id":"external_commands:scripts/with_server.py:69:python-subprocess-popen","reason":"The helper starts user-supplied server commands with shell=True. That creates real shell command execution risk if untrusted command text reaches --server.","verdict":"confirmed","severity":"high","confidence":0.9},{"id":"external_commands:SKILL.md:12:ruby-shell-backtick-execution","reason":"The backticks are Markdown formatting around a script path. This line does not execute Ruby, shell, or any command.","verdict":"false_positive","confidence":0.96},{"id":"external_commands:SKILL.md:14:ruby-shell-backtick-execution","reason":"The detected backticks only format the --help flag in Markdown. The separate prompt-influence concern from this line is captured as a semantic finding.","verdict":"false_positive","confidence":0.88},{"id":"external_commands:SKILL.md:18:ruby-shell-backtick-execution","reason":"This is a fenced Markdown decision tree, not executable Ruby or shell syntax. It only describes when to run a help command.","verdict":"false_positive","confidence":0.88},{"id":"external_commands:SKILL.md:33:ruby-shell-backtick-execution","reason":"The finding points at Markdown fence boundaries and nearby prose. There is no executable backtick command at this location.","verdict":"false_positive","confidence":0.93},{"id":"external_commands:SKILL.md:37:ruby-shell-backtick-execution","reason":"The backticks format the --help flag in documentation. Formatting a command option is not shell execution.","verdict":"false_positive","confidence":0.9},{"id":"external_commands:SKILL.md:40:ruby-shell-backtick-execution","reason":"The fenced bash example instructs agents to run the helper with an npm server command. It is legitimate usage, but still documents local external command execution.","verdict":"confirmed","severity":"medium","confidence":0.68},{"id":"external_commands:SKILL.md:42:ruby-shell-backtick-execution","reason":"The finding targets a Markdown fence boundary after the single-server example. The boundary itself is not shell execution.","verdict":"false_positive","confidence":0.91},{"id":"external_commands:SKILL.md:45:ruby-shell-backtick-execution","reason":"The fenced bash example includes cd, python, npm, and multiple --server commands. It documents shell-based local server startup that requires trusted inputs.","verdict":"confirmed","severity":"medium","confidence":0.7},{"id":"external_commands:SKILL.md:50:ruby-shell-backtick-execution","reason":"This location is the Markdown fence boundary and transition text after the command example. It does not itself execute a shell command.","verdict":"false_positive","confidence":0.92},{"id":"external_commands:SKILL.md:53:ruby-shell-backtick-execution","reason":"The fenced block is Python Playwright sample code for browser automation. It does not contain Ruby backtick execution or subprocess calls.","verdict":"false_positive","confidence":0.9},{"id":"external_commands:SKILL.md:63:ruby-shell-backtick-execution","reason":"The finding corresponds to a Markdown fence close and a heading. No shell command is executed at this location.","verdict":"false_positive","confidence":0.94},{"id":"external_commands:SKILL.md:68:ruby-shell-backtick-execution","reason":"The fenced Python snippet shows Playwright DOM inspection and screenshot calls. It is not external command execution.","verdict":"false_positive","confidence":0.91},{"id":"external_commands:SKILL.md:72:ruby-shell-backtick-execution","reason":"This is Markdown fence closure and ordinary prose. There is no executable shell or Ruby backtick pattern.","verdict":"false_positive","confidence":0.95},{"id":"external_commands:SKILL.md:80:ruby-shell-backtick-execution","reason":"The backticks format the word networkidle in documentation. This is not command execution.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:81:ruby-shell-backtick-execution","reason":"The backticks format a Playwright API call name in prose. They do not execute a shell command.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:85:ruby-shell-backtick-execution","reason":"The detected backticks format the scripts directory name. The black-box execution guidance is handled separately as a semantic concern.","verdict":"false_positive","confidence":0.88},{"id":"external_commands:SKILL.md:86:ruby-shell-backtick-execution","reason":"The backticks format the Playwright sync_playwright API name. This is not shell or Ruby command execution.","verdict":"false_positive","confidence":0.96},{"id":"external_commands:SKILL.md:88:ruby-shell-backtick-execution","reason":"The backticks format selector examples such as text= and role=. These are browser selector strings, not commands.","verdict":"false_positive","confidence":0.96},{"id":"external_commands:SKILL.md:89:ruby-shell-backtick-execution","reason":"The backticks format Playwright wait method names. This documentation text does not execute external commands.","verdict":"false_positive","confidence":0.96},{"id":"external_commands:SKILL.md:94:ruby-shell-backtick-execution","reason":"The backticks format an example filename. Referencing a filename in Markdown is not command execution.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:95:ruby-shell-backtick-execution","reason":"The backticks format an example filename and file URL concept. There is no shell or Ruby backtick execution.","verdict":"false_positive","confidence":0.96},{"id":"network:SKILL.md:59:hardcoded-url","reason":"The documented URL is localhost for a server the user already started. It is not an external network destination.","verdict":"false_positive","confidence":0.94},{"id":"filesystem:SKILL.md:69:temp-directory-access","reason":"The documentation shows saving an inspection screenshot to /tmp. This is local debugging output, not hidden filesystem access.","verdict":"false_positive","confidence":0.86}],"semantic_findings":[{"title":"Prompt Injection Attempt Detected","severity":"high","locations":[{"file":"SKILL.md","line_end":14,"line_start":14},{"file":"SKILL.md","line_end":85,"line_start":85}],"confidence":0.82,"description":"The skill says \"DO NOT read the source\" and promotes bundled scripts as black boxes before execution, which can suppress review of risky helper code.","confidence_reasoning":"The wording directly instructs agents to avoid source inspection before running bundled scripts. The risk is confirmed by the helper using shell=True, but the text may be intended as context management rather than malicious evasion."}],"subject_marketplace_commit_sha":null,"subject_content_hash":null,"subject_tree_hash":null,"subject_plugin_path":null,"audit_payload_hash":null,"confirmed_risk_level":null,"scanner_version":null,"policy_version":null,"subject":{"marketplaceCommitSha":null,"contentHash":null,"treeHash":null,"pluginPath":null,"auditPayloadHash":null},"scannerVersion":null,"policyVersion":null},"auditTranslation":null,"localization":{"requestedLocale":"en","contentLocale":"en","availableLocales":["en"],"fallbackToEnglish":false},"attestation":{"availability":"not_attestable","url":null,"status":null,"reason":"confirmed_risk_level does not match the canonical trust resolver"},"trust":{"publicState":"public","auditState":"complete","auditCurrentness":null,"confirmedRiskLevel":"high","confirmedFindingCount":1,"capabilityReviewCount":4,"needsReviewCount":0,"falsePositiveCount":0,"agentAutoInstallPolicy":"confirmation_required","manualInstallPolicy":"allowed","artifactSignatureState":"available","attestationState":"not_attestable","verificationState":"not_verified"},"isLatest":false}}