WPSigner for MainWP is a Dashboard admin extension. It has no public/nopriv AJAX endpoints. All actions require a logged-in user, a valid nonce (imwp_admin), and capability checks.
Documented behavior reflects addon v1.5.8 security hardening.
Capability Model
Section titled “Capability Model”can_manage() — use the extension
Section titled “can_manage() — use the extension”The user must:
- Be logged in
- Pass MainWP extension access for slug
insigner-mainwp, or havemanage_options - And (when WPSigner RBAC exists) pass
Permissions::can_use_signatures()
If WPSigner Permissions is unavailable, fallback is manage_options only after MainWP/admin gate.
Document mutations
Section titled “Document mutations”Send, remind, unlink, and access also require the document to be linked in MainWP and typically Permissions::can_modify_document (via bridge guards).
Templates
Section titled “Templates”Users without manage_options may only create from templates they own (template->user_id).
Signing Link Visibility
Section titled “Signing Link Visibility”Contract access (get_document_access) returns signing URLs only when can_view_signing_links() is true:
| Allowed | Condition |
|---|---|
| Yes | manage_options, or WPSigner Permissions::can_manage_all() |
| No | Other users who can still manage the extension — they see PDF actions when available, but signing links are hidden |
UI flag: signing_links_hidden. The modal shows a restricted message instead of Copy/Open.
OTP / KYC Trust Boundary
Section titled “OTP / KYC Trust Boundary”| Rule | Detail |
|---|---|
| Global policy lives in WPSigner | Security & Compliance (otp_mode / kyc_mode) |
MainWP does not mutate wps_options | v1.5.8 removed Off → per-document promotion |
| Per-document flags | Written only when gate mode is Choose per document and the Create/Quick create flag is on |
| KYC | Requires Didit ready in WPSigner |
Operators who need per-contract OTP/KYC from MainWP must set WPSigner policies to Choose per document first.
Rate Limits
Section titled “Rate Limits”Soft limits use per-user transients (~30 seconds):
| Action key | Scope |
|---|---|
create_send | Create-and-send / Quick create with send |
send | Send on an existing document |
remind | Remind (per document) |
Exceeded limit returns a friendly “wait a few seconds” error — not a hard lockout.
Orphan Protection
Section titled “Orphan Protection”If document create succeeds but MainWP link upsert fails, the addon deletes the draft document and returns an error. This prevents unlinked drafts accumulating in WPSigner.
AJAX Surface
Section titled “AJAX Surface”All handlers: wp_ajax_imwp_* (authenticated only).
| Action | Purpose |
|---|---|
imwp_create_document | Create from template |
imwp_quick_create | Quick create & send |
imwp_send_document | Send |
imwp_remind_document | Remind |
imwp_bulk_remind | Bulk remind (≤50) |
imwp_unlink_document | Unlink |
imwp_link_document | Link existing |
imwp_save_settings | Settings |
imwp_client_signer | Resolve client → signer (POST) |
imwp_document_access | Access modal payload (POST) |
Sensitive handlers read parameters from $_POST (not GET). Shared nonce action: imwp_admin.
SQL & XSS Posture
Section titled “SQL & XSS Posture”- Link/list queries use
$wpdb->preparewith whitelisted status/column fragments - Admin partials use
esc_html/esc_attr/esc_url admin.jsusesescapeHtml/ jQuery.text()for dynamic strings
What MainWP Does Not Do
Section titled “What MainWP Does Not Do”- No signing UI on child sites
- No anonymous signing endpoints
- No change to WPSigner global security options
- No deletion of WPSigner documents on Unlink or uninstall (uninstall drops link/activity tables only)
Reporting Issues
Section titled “Reporting Issues”If you discover a vulnerability in the addon or core, follow Report a Security Issue.