Documentation · Privacy, Security and Compliance
Security Recommendations
This document collects practical security recommendations for sites running the ADP Car Market Hub plugin. It focuses on operational hardening, the plugin's built-in protections and the controls site operators should configure on top of standard WordPress hardening.
This document does not replace a full security audit and does not guarantee that the site is free of vulnerabilities. Site operators should review their hosting setup, WordPress configuration and third-party integrations with a qualified security specialist where appropriate.
When to use this document
Use this document when you need to:
- Prepare a site that uses the plugin for production use.
- Review the plugin's built-in security controls.
- Plan operational security measures (credentials, cron, logging, backups).
- Respond to an internal security review or questionnaire.
Overview
The plugin relies on standard WordPress security primitives:
- WordPress capabilities (custom plugin capability
manage_as24_importsfor management actions; per-CPT capabilities for vehicle posts). - WordPress nonces on every admin form, AJAX action and admin POST handler.
- Standard WordPress sanitization and escaping helpers
(
sanitize_*,wp_kses_post,esc_*,wp_unslash). - WordPress transients for short-lived state (rate limits, run locks).
- The site's existing TLS, login protection, file permissions and database security.
The plugin adds several feature-specific protections on top of those primitives, listed in the next section.
Built-in protections
The behaviors below reflect what the plugin code implements today. Verify them in the current plugin version before relying on them in formal security documentation.
Authentication and authorization
- Admin pages and POST handlers check the plugin management capability
(
manage_as24_imports) before processing any state change. - Admin AJAX endpoints in the plugin verify a nonce via
check_ajax_referer. - Admin form submissions use
check_admin_refererwith form-specific nonce actions. - Custom capabilities are mapped for the
as24ci_carpost type withmap_meta_cap = true, so per-post permissions follow the WordPress meta-cap mechanism.
REST API surface
- The public vehicles REST routes (
/wp-json/as24ci/v1/vehiclesand/wp-json/as24ci/v1/vehicles/{id}) are only registered when the Enable REST API option is on. They use apermission_callbackof__return_true, meaning the data they return is intended to be public read-only. Disable the option if you do not want to expose this surface. - The cron import endpoint (
/wp-json/as24ci/v1/cron-import) registers a public route but performs token-based authentication inside the callback. The token is compared withhash_equals(constant-time comparison) and is required on every call. - The cron token can be supplied as either an
Authorization: Bearerheader (preferred — keeps the token out of access logs) or as a?token=query parameter.
Cron token
- The cron token is managed from the plugin's import settings and is
stored in the
as24ci_cron_tokenoption as a one-way HMAC-SHA256 hash, so the plaintext cannot be recovered from a database dump. The plaintext value is only available in the admin UI for a short display window (around 15 minutes) immediately after the token is generated or regenerated; after that window the admin can only regenerate a new token, not reveal the previous one. - The endpoint refuses requests when no token is configured.
Contact form anti-abuse
- Every submission must carry the
as24ci_contact_formnonce. - A hidden
websitehoneypot field silently rejects automated submissions without producing a visible error. - A rate limit of 5 submissions per IP per 5 minutes is enforced through
a WordPress transient. The IP address is hashed with
wp_salt('auth')before use and is not stored with the lead. - The message field is filtered with
wp_kses_post.
Search alert tokens
- Each subscription has a 64-character cryptographically random token used for both the confirmation link and the unsubscribe link.
- Confirmation only flips a row from
pendingtoactive; subsequent uses do not change the state again.
Logger and secret masking
- The plugin's logger writes to a file inside a dedicated subdirectory
of the WordPress uploads folder (
as24ci-logs/). - On creation, the directory is protected by an
.htaccessfile that denies all access (Apache only) and an emptyindex.phpfile. - Before each line is written, the message is sanitized to mask
token=…,client_secret=…andAuthorization: Bearer …fragments (defence in depth). - Logs rotate at 10 MB and rotated files older than 7 days are deleted automatically.
- On servers that do not honor
.htaccess(Nginx, Caddy, IIS), the upload directory exposure depends on the web server configuration. Operators should ensure that direct access towp-content/uploads/as24ci-logs/is blocked on such servers.
Data on uninstall
- The analytics and search agent tables are dropped unconditionally on uninstall, so visitor tracking data and subscriber email addresses do not persist after the plugin is removed.
- The optional Delete data on uninstall setting also removes vehicle posts, lead posts, plugin pages and imported attachments.
Recommended operator actions
The recommendations below combine standard WordPress hardening with plugin-specific configuration.
Credentials and secrets
- Treat the AutoScout24 API client secret and the cron token as
sensitive secrets. They are stored as WordPress options but are
protected at rest by the plugin's centralised secrets helper: the
client secret is encrypted with authenticated AES-256-GCM (key
derived from the WordPress salts via HKDF-SHA256), and the cron
token is stored as a one-way HMAC-SHA256 hash so the plaintext
cannot be recovered from a database dump. Standard WordPress
database hardening still applies.
The managed Gemini API key used by the AI assistant is configured by
AD Promotion in
AS24CI\Ai_Configand is not stored as a WordPress option or exposed in the admin UI. - Restrict database access to administrators and ensure
wp-config.phpis not world-readable. - Rotate the cron token if there is any reason to suspect it was
exposed (for example through access logs that recorded the
?token=query parameter).
REST and cron endpoint
- Disable Enable REST API if you do not need to expose the public vehicle endpoints.
- When using the built-in cron endpoint, prefer
Authorization: Bearer YOUR_TOKENover?token=…so the secret does not appear in web server access logs. - Use HTTPS for any external scheduler that calls the cron endpoint.
- Prefer a reliable system cron triggering WP-Cron over the default pseudo-cron behavior on production sites.
Roles and capabilities
- Grant the
manage_as24_importscapability only to trusted users. By default it is added to theadministratorrole. - Use the plugin's
as24ci_editorrole (or a comparable custom configuration) for staff who only need to manage vehicle posts and not the plugin settings. See Access Control and Capabilities.
Privacy and analytics
- Keep analytics off until you have a documented legal basis or a consent integration in place. See GDPR / DSGVO Notes and revDSG Notes.
- Keep Filter data minimization enabled.
- Set the analytics retention window to the lowest value compatible with your operational needs (minimum 7 days).
Forms and lead handling
- Keep optional fields (Phone, Message) hidden if you do not need them.
- Configure the lead notification email recipient and verify it is a controlled mailbox.
- Consider an SMTP plugin and SPF/DKIM/DMARC alignment to reduce the risk of inquiry emails being filtered as spam.
- Periodically delete leads that are no longer needed for legitimate business purposes.
AI assistant feature
- The AI assistant uses the managed Google Gemini configuration in ADP Car Market Hub. No provider selection, model selection or API key entry is required in the WordPress backend; customer-specific AI provisioning is completed by AD Promotion after installation. Prompts are sent to the managed Gemini endpoint over HTTPS.
- Restrict who can configure the AI assistant by limiting the
manage_as24_importscapability. - Review the applicable data processing and contractual terms for the managed AI setup before enabling AI features in production.
File system and uploads
- Verify that the WordPress uploads directory is not directory-listable on your web server.
- On non-Apache servers (Nginx, Caddy, IIS), confirm that
wp-content/uploads/as24ci-logs/is not publicly accessible. The plugin writes an.htaccessfor protection on Apache; on other servers operators must add an equivalent rule. - Keep PHP, WordPress, themes and other plugins up to date.
Backups and incident response
- Include the WordPress database in regular backups; this captures vehicle posts, leads, analytics and search alert data.
- Test backup restoration periodically.
- Document an incident response plan, including how to disable the cron endpoint (clear the cron token) and revoke the API client secret. To disable AI features, deactivate the AI assistant from the AI Assistant admin tab; the managed Gemini key is owned and rotated by AD Promotion.
Step by step: pre-production security checklist
- Confirm WordPress, the plugin and all other plugins/themes are on their current stable versions.
- Confirm that the site is served over HTTPS and that admin sessions are restricted to HTTPS.
- Review the WordPress users list and roles. Remove unused accounts.
- Confirm that only trusted users hold the
manage_as24_importscapability. - Decide whether the public REST routes are needed. Disable Enable REST API if not.
- If the cron endpoint is used, generate a long random cron token
and call it via
Authorization: Bearer …over HTTPS. - Configure the lead form's recipient email and consent settings.
- Review the analytics settings (off by default; if enabled, set retention and consent integration).
- Verify that the log directory is not publicly accessible on your web server.
- Take a baseline backup before going live.
Troubleshooting
- Public users can call admin AJAX or admin POST handlers — check that you are not running with debug helpers that bypass capabilities; the plugin's handlers verify both the capability and the nonce on every request.
- Cron endpoint returns
403 Invalid or missing token— verify the cron token is configured in the plugin admin and that the caller supplies it correctly viaAuthorization: Beareror?token=. - Cron endpoint returns
403 Cron token not configured— open the plugin's import settings and generate / set the cron token. - Logs not rotating — confirm that the uploads directory is writable and that WP-Cron is running. Rotation is checked periodically (on the first call and every 100 calls thereafter).
- Sensitive values appear in logs — the logger masks known patterns. If a custom integration logs additional secrets, update that integration to mask them at the source.