WP Manifestindependent plugin directory
manifest / ai / gravity-extract

Gravity Extract WP Registry grade D+. High-severity findings · 3 findingsWP RegistryHigh-severity findings · 3 findingsOpen the reportD+

A WordPress plugin that integrates with Gravity Forms to automatically extract data from uploaded documents using AI vision models.

★ 0stars
24release downloads
≈10active sites
v1.1.1latest · 6mo ago

Install

Download gravity-extract.zip From the v1.1.1 release on GitHub, Mar 31, 2026

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/guilamu/gravity-extract/releases/download/v1.1.1/gravity-extract.zip
Updates itself. It ships its own updater, so new versions appear under Dashboard → Updates.

AI-powered document data extraction for Gravity Forms. Upload invoices or receipts and automatically populate form fields using powerful AI vision models via POE or Google Gemini APIs.

Document Upload

  • Drag & Drop Interface: Easy-to-use upload area for document images and PDFs.
  • Multi-Format Support: Handles JPEG, PNG, WebP, and multi-page PDFs (automatically converted).
  • Real-Time Feedback: Visual progress indicators and immediate preview of uploaded documents.

AI-Powered Extraction

  • Multi-Provider Support: Choose between POE API (GPT-4o, Claude, Gemini via POE) or Google Gemini API (direct).
  • Vision Model Integration: Connects with powerful AI vision models for document analysis.
  • Smart Data Parsing: Extracts merchant details, amounts, dates, and line items with high accuracy.
  • Structured JSON Output: Returns clean, structured data ready for form population.

Field Mapping

  • Flexible Mapping System: Associate extracted data with any Gravity Forms field type.
  • AI Auto-Mapping: Automatically suggests the best connections between extracted data and form fields.
  • Custom Profiles: Save, export, and reuse mapping configurations for different document types.

Key Features

  • AI Field Detection: Automatically detects available fields in custom documents
  • Per-Form Configuration: Each form can use a different API provider, key, and model
  • Multilingual: Works with content in any language
  • Translation-Ready: All strings are internationalized
  • Secure: API keys are stored per form with no external data leakage
  • GitHub Updates: Automatic updates from GitHub releases

Supported API Providers

POE API

  • Access to GPT-4o, Claude, Gemini, and many other models through a single API key
  • Dynamic model list fetched from the POE API
  • Get your API key at poe.com/api_key

Google Gemini API (Direct)

  • Gemini Flash — Fast and cost-effective
  • Gemini Pro — Most capable model
  • Uses the OpenAI-compatible endpoint for seamless integration
  • Get your API key at aistudio.google.com/apikey

Requirements

  • A POE API Key or a Google Gemini API Key
  • WordPress 5.0 or higher
  • PHP 7.4 or higher
  • Gravity Forms 2.5 or higher

Installation

  1. Upload the gravity-extract folder to /wp-content/plugins/
  2. Activate the plugin through the Plugins menu in WordPress
  3. Go to your form's Settings → Gravity Extract tab
  4. Select your API Provider (POE or Gemini)
  5. Enter your API key and select a model
  6. Add a Gravity Extract field to your form to start using it

FAQ

How do I get an API key?

Can I use different providers for different forms?

Yes! Each form has its own Gravity Extract settings tab where you can independently choose the API provider, key, and model.

Does it work with PDFs?

Yes, multi-page PDFs are supported. The plugin converts them to images for the AI model to analyze.

Can I customize the extraction prompt?

Yes, use the gravity_extract_prompt filter:

add_filter('gravity_extract_prompt', function($prompt) {
    return $prompt . "\nAlso extract the warranty period.";
});

Project Structure

.
├── gravity-extract.php              # Main plugin file
├── README.md
├── css
│   ├── gravity-extract-admin.css    # Admin styles
│   └── gravity-extract-frontend.css # Frontend styles
├── includes
│   ├── class-gravity-extract.php        # Core plugin class
│   ├── class-gemini-api-service.php     # Google Gemini API service
│   ├── class-github-updater.php         # GitHub auto-updates
│   ├── class-gravity-extract-addon.php  # GF Addon settings
│   ├── class-gf-field-gravity-extract.php # Custom GF field
│   ├── class-mapping-profiles-manager.php # Profiles manager
│   └── class-poe-api-service.php        # POE API service
└── js
    ├── gravity-extract-admin.js     # Admin scripts
    └── gravity-extract-frontend.js  # Frontend scripts

Changelog

1.1.1

  • Improved: Rewritten GitHub updater with README.md parsing for "View details" popup
  • New: "View details" thickbox link in plugin row meta
  • New: Parsedown.php for reliable Markdown-to-HTML conversion
  • Improved: Plugin info popup now shows Description, Installation, FAQ, and Changelog tabs

1.1.0

  • New: Added Google Gemini API as an alternative AI provider
  • New: Per-form API provider selection (POE or Gemini)
  • New: Gemini API key and model settings per form
  • New: Gemini Flash and Gemini Pro model support
  • Improved: Provider-aware API routing for all extraction features (analyze, automap, detect)
  • Improved: Updated README with multi-provider documentation

1.0.3

  • Minor fixes

1.0.2

  • Security: Fixed SSL verification issue in POE API service
  • Performance: Increased memory limit for image processing
  • Improvement: Cleaned up debug logs for better production hygiene

1.0.1

  • New: Added GitHub auto-update support
  • Improved: Updated README documentation structure

1.0.0

  • Initial release
  • AI-powered document extraction
  • Gravity Forms integration
  • Drag and drop upload
  • Field mapping profiles

License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) - see the LICENSE file for details.


Made with love for the WordPress community

Releases

4 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
v1.1.1 latest
Mar 31, 2026 6mo ago
gravity-extract.zip
8
Feb 21, 2026 8mo ago
gravity-extract.zip
6
Feb 16, 2026 8mo ago
gravity-extract.zip
6
Jan 8, 2026 9mo ago
gravity-extract.zip
4

Active-site estimate ≈10 comes from the median of recent superseded releases. Method.

D+ grade

Security

Gravity Extract 1.1.1 · audited by WP Registry

High-severity findings.

2 high 1 medium
Audited release
1.1.1
Findings
3
Worst severity
high
Content hash
0484aa8a813c3e46cc7446d0…

Findings

  • high Unauthenticated AJAX upload writes files without form, field, or type checks

    file_access

    wp_ajax_nopriv_gravity_extract_upload_file maps to Gravity_Extract::ajax_upload_file. The only gate is check_ajax_referer('gravity_extract_frontend'), whose nonce is localized on any public Gravity Form that contains a gravity_extract field and is not bound to a form_id. form_id and field_id are optional integers; wp_handle_upload($file, array('test_form' => false)) runs before any GFAPI::get_form / field-type check, and no mimes/allowedExtensions allowlist is passed (the field UI advertises jpg/png/webp/pdf and a 10MB cap, but those exist only in JavaScript). WordPress then accepts the full get_allowed_mime_types() set (documents, audio, video, archives, etc.). Success JSON includes both the public uploads URL and the absolute server path. application/pdf uploads are converted with Imagick::readImage($pdf_path . '[' . $i . ']') (up to 10 pages at 150 DPI, memory_limit raised to 512M) — untrusted PDFs processed by Ghostscript/ImageMagick. Uploaded files are never attached as media, never moved into Gravity Forms' hashed directory, and are not deleted if the visitor never submits the form, so a scraped uid-0 nonce enables unlimited public-file planting and disk fill for 12–24 hours.

    includes/class-gravity-extract.php:489-565

    Recommendation

    Reject the request unless form_id/field_id resolve to a published form whose field type is gravity_extract. Bind the nonce to the form (or include a per-form token). Pass an explicit mimes map matching the field's allowedExtensions (default jpeg/png/webp/pdf) into wp_handle_upload, enforce a server-side size cap, and do not return the filesystem path. Store files in a non-listable Gravity Forms-style hashed directory. Rate-limit by IP. Treat uploaded PDFs as untrusted (disable Imagick if possible; at least limit pages/pixels and fail closed).

  • high Unauthenticated analyze endpoint spends any form's stored AI API keys

    dos

    wp_ajax_nopriv_gravity_extract_analyze (and the upload handler's post-upload analysis branch) is reachable with the same global gravity_extract_frontend nonce. After the nonce check, the handler takes attacker-controlled form_id/field_id/image_base64, loads the form via GFAPI::get_form (works for inactive/non-embedded forms), and reads gravity_extract_api_key / gravity_extract_gemini_api_key plus the model from that form's add-on settings. There is no current_user_can, no check that the form is publicly embeddable, no binding of the nonce to form_id, no rate limit, and no cap on image_base64 size. The image is then POSTed to https://api.poe.com/v1/chat/completions or https://generativelanguage.googleapis.com/v1beta/openai/chat/completions using the site owner's secret. A visitor who loads any public form that merely contains a gravity_extract field can enumerate form_id/field_id and burn every configured form's POE/Gemini quota (and PHP memory) without submitting an entry.

    includes/class-gravity-extract.php:393-484

    Recommendation

    Bind the frontend nonce (or a second token) to form_id. Refuse analysis unless that form is currently displayed/published and the field is gravity_extract with mappings. Rate-limit per IP and per form, reject oversized base64, and do not raise memory_limit for unauthenticated requests. Keep API keys server-side (already done) but treat each key as scoped to its form.

  • medium Entry save always dumps full form POST to the PHP error log

    information_disclosure

    GF_Field_Gravity_Extract::get_value_save_entry runs on every Gravity Forms submission that includes this field. Seven error_log() calls are unconditional (not gated on WP_DEBUG), including print_r($_POST, true). Mapped extraction fields are designed to hold invoices, VAT numbers, and bank_IBAN / bank_BIC values; those plus other GF inputs and nonces are therefore written to the PHP error log on every submit. On many hosts error_log is a web-reachable file (public_html/error_log or wp-content/debug.log). The same method also returns rgpost('input_{id}_file') without esc_url_raw/parent::sanitize_entry_value, so the stored value is whatever the submitter posted, but the immediate observable harm is PII/secret leakage into logs. convert_pdf_to_jpeg() and the POE/Gemini analyze_image_with_keys() helpers likewise error_log without a WP_DEBUG guard.

    includes/class-gf-field-gravity-extract.php:176-189

    Recommendation

    Remove leftover debug logging from production paths. If logging is needed, gate it on WP_DEBUG and never print $_POST or file contents. Sanitize the saved file value with esc_url_raw() (and verify it matches a file this request actually uploaded). In get_value_merge_tag, honor $esc_html / $url_encode instead of returning the raw stored string.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.