Files
ns_erpnext_app/docs/SECURITY_NOTES.md
norman 8bb8954ff6 docs: add architecture, design spec, and security notes
Analyze the NS App and document what it does: NMI card payments on
Sales Invoices, AutoPay vaulting, multi-invoice settlement, guided
Customer Quick Entry, and branded print formats.

- docs/ARCHITECTURE.md  — functional overview, component map, payment
  flow, data model, dependencies, config, known tech debt
- docs/DESIGN_SPEC.md   — goals, requirements, API contracts, failure
  modes, acceptance criteria
- docs/SECURITY_NOTES.md — posture + hardening list
- docs/README.md        — docs index; link from root README

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 07:33:32 -04:00

34 lines
2.2 KiB
Markdown

# NS App — Security Notes & Hardening
Companion to [ARCHITECTURE.md](./ARCHITECTURE.md) §9 and
[DESIGN_SPEC.md](./DESIGN_SPEC.md) §7.
## Current posture (as implemented)
- **PCI scope minimized.** Card number, expiry, and CVV are entered into
NMI-hosted Collect.js iframes. ERPNext receives only a single-use
`payment_token`. Raw card data never reaches the browser JS context or the
server.
- **No card storage.** Only the NMI Customer Vault ID is persisted on the
Customer (`custom_auto_pay_id`).
- **Secret handling.** `nmi_security_key` is read from `site_config.json`
(server-side) and sent only in server→NMI requests.
- **Transport.** All gateway calls use HTTPS to `secure.nmi.com`.
## Gaps & recommended hardening
| # | Issue | Recommendation |
|---|-------|----------------|
| 1 | **Unauthenticated webhook.** `crystalclear_webhook` is `allow_guest=True` and creates Payment Entries from any POST whose `orderid` matches an invoice. | Require a shared secret / HMAC signature; verify before writing. Optionally allow-list source IPs. |
| 2 | **Debug logging of gateway payloads.** `payments.py` writes request/response snippets via `frappe.log_error`. | Confirm no PAN/PII is ever logged; use a dedicated logger at an appropriate level; consider truncation/redaction and log retention limits. |
| 3 | **Hard-coded tokenization key** in `sales_invoice.js`. | Move to a server-provided value / site config; makes key rotation and per-environment keys possible. |
| 4 | **Hard-coded ledger account** `"ENB Bank Account - NIL"`. | Make company-aware via config or a Company-level custom field. |
| 5 | **Permissions.** Payment endpoints are whitelisted to any logged-in user. | Add role checks (as `create_customer_full` does with `frappe.only_for`) and/or rate limiting. |
| 6 | **`ignore_permissions=True`** on Payment Entry and Customer writes. | Acceptable for a system flow, but document the trust boundary and ensure the whitelisted entry points are themselves access-controlled. |
## Operational reminders
- Keep `enable_autopay_signup = 0` in production until vaulting is fully tested.
- Never commit `site_config.json` or the NMI security key to version control.
- Rotate the NMI security key and Collect.js key on any suspected exposure.