Sensitive-Data
Hazard Scan
A pattern-based review of every custom field definition in this NetSuite account, identifying fields that store credentials or duplicate regulated personal data outside native, governed fields. Counts only — no stored values were retrieved into this report.
Verdict: action required. Live plaintext credentials were confirmed in two custom fields, populated on 17 records. One secret surfaced during scanning and must be treated as exposed.
Executive summary
2,485 custom field definitions were scanned. Two live hazards were confirmed — both store credential material in plain, unencrypted text fields readable by any role with record access.
Plaintext API credentials are live in this account today. The field custrecord_filing_authorization_cred holds what appears to be an active client id + secret pair in JSON on both records of the Online Filing Authorization record type. A second field, custrecord_ccp_gateway_cred_id, is populated on all 15 Additional Credential records. Neither field is encrypted, masked, or restricted beyond ordinary record permissions.
During schema verification, the credential value surfaced in diagnostic output — treat that secret as exposed and rotate it regardless of any other action taken.
Scan funnel
How 2,485 field definitions were reduced to 2 confirmed live hazards. Each stage is fully reproducible from the queries in section 05.
Findings
Thirteen fields survived triage. Filter by severity or search any scriptid, label, record type, or owner.
CUSTOMRECORD_FILING_AUTHORIZATION — Online Filing Authorization (160)CUSTOMRECORD_CCP_GATEWAY_ADD_CRED — Additional Credential (507)CUSTOMRECORD_CCP_PAYU_CONFIG_REC — PayU Account Info & Credentials (504)CUSTOMRECORD_CCP_ASIAPAY_CONFIG_REC — AsiaPay Account Info (506)CUSTOMRECORD_CCP_ASIAPAY_DIRECT_CONFIG — AsiaPay Payment Account Info (510)CUSTOMRECORD_NS_SC_EXT_SN_SUBSCRIPTION — Stock Notifications Subscription (241)CUSTOMRECORD_CCT_NETSUITE_MAPCONTACTCCT — CCT Map & Contact Info (393)CUSTOMRECORD_ECSL_AUDIT_TRAIL_DTL (19) · _HDR (17)CUSTOMRECORD_NS_POS_PAYMENT_METHOD (199)Cleared Excluded as false positives
≈146 raw hits were dismissed on review: “Author” / “Authorization” / “Authorized Roles” fields (blog authorship and POS approval-role selectors caught by %AUTH%) · “activation” and manufacturing “routing” collisions · email template-text fields (button labels, validation messages) holding no personal data · product-review rating fields caught by an over-broad substring.
Population analysis
Fill rate of each hazard field — populated rows over total rows on the host record type. Blue marks fields requiring action. Hover any bar for detail.
Plaintext client id + secret · HIGH
Classification pending · HIGH
Consumer PII outside entity model · MEDIUM
Low practical risk
Dormant — restrict before use
Dormant — restrict before use
Every credential-pattern field whose host record type is populated is populated at 100% — these fields are in active use, not residue. Empty bars are dormant definitions: cheap to remediate now, before data arrives.
Methodology & queries
Read-only SuiteQL against the customfield metadata table, verified with COUNT() aggregates only. Every query is reproducible — use the copy button on each block.
Pattern match on metadata. Field names and scriptids matched against two hazard dictionaries — credential terms (password, secret, token, API key, credential, auth, private key) and regulated-data terms (email, phone, SSN, tax id, EIN/TIN, VAT, credit card, CVV, bank account, routing, IBAN, date of birth). Field value types “Email Address” and “Phone Number” matched directly.
False-positive triage. Each raw hit reviewed in context — “Author” ≠ “Auth”, “Activation” ≠ “VAT”, “Routing Rule” ≠ bank routing — and template-text fields excluded. 159 raw hits → 13 verified.
Population verification. Survivors checked with count-only queries against host tables. Owners resolved via employee; record types via customrecordtype. No stored values read into the report.
Q1Credential-pattern scan of custom field metadata18 hits → 6 kept
SELECT id, scriptid, name, description, fieldtype, fieldvaluetype, recordtype, isstored, owner, lastmodifieddate FROM customfield WHERE UPPER(name) LIKE '%PASSWORD%' OR UPPER(scriptid) LIKE '%PASSWORD%' OR UPPER(scriptid) LIKE '%PASSWD%' OR UPPER(scriptid) LIKE '%PWD%' OR UPPER(name) LIKE '%SECRET%' OR UPPER(scriptid) LIKE '%SECRET%' OR UPPER(name) LIKE '%TOKEN%' OR UPPER(scriptid) LIKE '%TOKEN%' OR UPPER(name) LIKE '%API KEY%' OR UPPER(name) LIKE '%APIKEY%' OR UPPER(scriptid) LIKE '%APIKEY%' OR UPPER(scriptid) LIKE '%API_KEY%' OR UPPER(name) LIKE '%CREDENTIAL%' OR UPPER(scriptid) LIKE '%CREDENTIAL%' OR UPPER(name) LIKE '%AUTH%' OR UPPER(scriptid) LIKE '%AUTH%' OR UPPER(name) LIKE '%PRIVATE KEY%' OR UPPER(scriptid) LIKE '%PRIVKEY%' ORDER BY fieldtype, scriptid
12 of the 18 raw hits were Author / Authorization false positives dismissed on review.
Q2Regulated-data pattern scan (refined)13 hits
SELECT id, scriptid, name, fieldtype, fieldvaluetype, recordtype, isstored, owner FROM customfield WHERE fieldvaluetype IN ('Email Address', 'Phone Number') OR UPPER(name) LIKE '%SSN%' OR UPPER(name) LIKE '%SOCIAL SECURITY%' OR UPPER(name) LIKE '%TAX ID%' OR UPPER(scriptid) LIKE '%TAXID%' OR UPPER(name) LIKE '%BANK ACCOUNT%' OR UPPER(name) LIKE '%ROUTING%' OR UPPER(name) LIKE '%IBAN%' OR UPPER(name) LIKE '%CREDIT CARD%' OR UPPER(name) LIKE '%CVV%' OR UPPER(name) LIKE '%BIRTH%' OR UPPER(scriptid) LIKE '%_DOB%' OR UPPER(name) LIKE '%VAT REG%' OR UPPER(scriptid) LIKE '%VAT_REG%' OR UPPER(scriptid) LIKE '%VATNO%' OR (UPPER(name) LIKE '%EMAIL%' AND fieldtype IN ('ENTITY','BODY','COLUMN')) OR (UPPER(name) LIKE '%PHONE%' AND fieldtype IN ('ENTITY','BODY','COLUMN')) ORDER BY fieldtype, scriptid
A first, broader pass (141 hits) was discarded after bare %VAT% and %MOBILE% patterns matched “activation” and device-layout fields. This refined version returned 13.
Q3Owner and record-type resolution
SELECT id, entityid, firstname, lastname, email FROM employee WHERE id IN (1548, 1550, 1576); SELECT internalid, scriptid, name FROM customrecordtype WHERE internalid IN (17, 19, 33, 160, 191, 199, 218, 241, 393, 504, 506, 507, 510);
Owner −5 denotes a system / bundle installation account.
Q4Population verification — counts only, no values
-- Host-table row counts SELECT 'CCP_ASIAPAY_CONFIG_REC' AS tbl, COUNT(*) FROM customrecord_ccp_asiapay_config_rec UNION ALL SELECT 'CCP_ASIAPAY_DIRECT_CONFIG', COUNT(*) FROM customrecord_ccp_asiapay_direct_config UNION ALL SELECT 'CCP_GATEWAY_ADD_CRED', COUNT(*) FROM customrecord_ccp_gateway_add_cred UNION ALL SELECT 'FILING_AUTHORIZATION', COUNT(*) FROM customrecord_filing_authorization UNION ALL SELECT 'EF_BS_SUSCRIPTION', COUNT(*) FROM customrecord_ef_bs_suscription UNION ALL SELECT 'NS_SC_EXT_SN_SUBSCRIPTION', COUNT(*) FROM customrecord_ns_sc_ext_sn_subscription UNION ALL SELECT 'NS_POS_PAYMENT_METHOD', COUNT(*) FROM customrecord_ns_pos_payment_method UNION ALL SELECT 'CCT_NETSUITE_MAPCONTACTCCT', COUNT(*) FROM customrecord_cct_netsuite_mapcontactcct UNION ALL SELECT 'ECSL_AUDIT_TRAIL_HDR', COUNT(*) FROM customrecord_ecsl_audit_trail_hdr UNION ALL SELECT 'ECSL_AUDIT_TRAIL_DTL', COUNT(*) FROM customrecord_ecsl_audit_trail_dtl; -- Field-level fill rates (COUNT(col) counts non-null only) SELECT COUNT(custrecord_ccp_gateway_cred_id), COUNT(*) FROM customrecord_ccp_gateway_add_cred; SELECT COUNT(custrecord_ns_pos_pm_cc_pattern), COUNT(*) FROM customrecord_ns_pos_payment_method; SELECT COUNT(custrecord_ns_sc_ext_sn_s_email), COUNT(*) FROM customrecord_ns_sc_ext_sn_subscription; SELECT COUNT(custrecord_cct_ns_mcicct_phonenumber), COUNT(*) FROM customrecord_cct_netsuite_mapcontactcct; SELECT COUNT(custrecord_cct_ns_mcicct_primaryemail), COUNT(*) FROM customrecord_cct_netsuite_mapcontactcct; SELECT COUNT(custrecord_acct_bank_account_number), COUNT(*) FROM account; SELECT COUNT(custbody_ns_pos_signature_image) FROM transaction;
custrecord_filing_authorization_cred is not exposed as a SuiteQL column; its population (2 of 2) was confirmed via record-schema introspection instead.
Q5Coverage denominator
SELECT COUNT(*) AS total_fields, SUM(CASE WHEN isstored = 'T' THEN 1 ELSE 0 END) AS stored_fields FROM customfield; -- 2,485 total · 2,406 stored
Assumptions & limitations
• Name-based detection only. A field named innocuously (e.g., “Config Value”) that actually stores a secret will not be caught. Free-text fields, long-text blobs, and file-cabinet contents were not content-scanned.
• Populated ≠ sensitive. “Additional Credential ID” (15/15) may hold reference identifiers rather than secrets — values were deliberately not read. Manual review of one record is recommended.
• CUSTENTITY_VAT_REG_NO could not be population-checked — not applied to customer or vendor record types, not exposed to SuiteQL. Assumed dormant.
• Owner attribution reflects the field's owner attribute; for bundle-installed fields this is the installing user or system account (−5), not necessarily the current maintainer.
• Scope is custom field definitions. Native fields, saved-search exposure, deployment-level script parameters, and workflow custom fields were out of scope for this pass.
• The scan ran under role id 3 on 2026-09-04; fields hidden from this role by field-level security would not appear.
Remediation roadmap
Six steps, ordered by urgency. Click a task to mark it complete — progress is saved in this browser and shown in the sidebar. (Checkmarks are a local working aid; they do not change anything in NetSuite.)
The client id + secret in custrecord_filing_authorization_cred surfaced in plaintext during this scan and is visible to any role with view access to record type 160. Rotate at the issuing provider first, then remediate storage.
Replace plain custom fields with API Secrets (Setup > Company > API Secrets) referenced via secure strings in script. Blank the legacy field values after migration.
Open one customrecord_ccp_gateway_add_cred record: if the field holds gateway secrets, apply the previous step; if reference ids, downgrade and close the finding.
Lock CUSTOMRECORD_CCP_PAYU_CONFIG_REC, both AsiaPay config types, and CUSTOMRECORD_CCP_GATEWAY_ADD_CRED to administrator-only record permissions before they are populated.
Ensure CUSTOMRECORD_NS_SC_EXT_SN_SUBSCRIPTION is included in data-subject-access and erasure procedures, or link subscribers to entity records.
Queries Q1–Q2 are reusable as-is. Consider deleting unused bundle fields (CUSTENTITY_VAT_REG_NO, bank-account and signature fields) if their bundles are retired — an empty hazard field is still an invitation.
Disclaimer. This report was generated by an automated, pattern-based scan executed on September 4, 2026 under the requesting user's NetSuite role. It is a point-in-time configuration review, not a comprehensive penetration test or a guarantee of compliance with GDPR, PCI-DSS, or any other regulation. No stored field values are reproduced in this document; population figures are non-null row counts only. Findings should be validated by the data owner before remediation. Source: SuiteQL queries against customfield, customrecordtype, employee, and host record tables in account TD3096877.
Chartstone · Sensitive-Data Hazard Scan · September 2026