WP Manifestindependent plugin directory
manifest / content / wordpress-fieldmanager

Fieldmanager WP Registry grade B-. Medium-severity findings · 3 findingsWP RegistryMedium-severity findings · 3 findingsOpen the reportB- #4 in Content & Publishing

Custom field types for WordPress

★ 564stars
945kcomposer installs
v1.6.3latest · 2mo ago

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/alleyinteractive/wordpress-fieldmanager/archive/refs/heads/main.zip

On Packagist as alleyinteractive/wordpress-fieldmanager:

composer require alleyinteractive/wordpress-fieldmanager
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Fieldmanager is a comprehensive toolkit for building forms, metaboxes, and custom admin screens for WordPress.

Using Fieldmanager in your WordPress Project

Fieldmanager is a powerful library which can make the development of sophisticated features a breeze. To get started, simply download and install this plugin into your plugins directory and activate it on the plugins screen. To learn how to use Fieldmanager's API, visit the project's official website at Fieldmanager.org. There is also a demo plugin which illustrates a lot of what you can do with Fieldmanager.

Requirements

  • WordPress: 5.8+
  • PHP: 8.1+

Downloads and Versioning.

You can view Fieldmanager's official releases here.

The main branch on GitHub is the "bleeding edge" release. As of 1.0, Fieldmanager will maintain a typical release cycle, with alpha, beta, and RC releases, and we hope to move through "minor" versions pretty quickly. While we encourage everyone to develop with and test on early releases and help us find the bugs, stable releases are recommended for production.

Contributing to Development

Development of Fieldmanager happens on GitHub. Bugs with Fieldmanager should be addressed in the GitHub issue queue, and enhancements or bug fixes should be submitted as pull requests, which are always welcome.

Generating Documentation

To build Fieldmanager's API documentation, the latest version of which is available at api.fieldmanager.org, you need apigen installed. Once you've got that, you can generate the entire documentation tree as follows:

apigen -c apigen.neon

Releases

24 releases.

Tag
Published
v1.6.3 latest
Aug 12, 2026 2mo ago
May 15, 2026 5mo ago
May 6, 2024 2 years ago
Dec 1, 2023 2 years ago
Mar 30, 2022 4 years ago
Mar 1, 2022 4 years ago
Feb 8, 2022 4 years ago
Feb 4, 2022 4 years ago
Jan 7, 2022 4 years ago
Dec 14, 2021 4 years ago
Jun 22, 2020 6 years ago
May 13, 2020 6 years ago
Jan 11, 2019 7 years ago
May 5, 2018 8 years ago
Apr 4, 2018 8 years ago
Jan 8, 2018 8 years ago
Nov 5, 2017 8 years ago
Oct 6, 2017 9 years ago
Mar 4, 2016 10 years ago
Feb 22, 2016 10 years ago
Dec 31, 2015 10 years ago
Jan 16, 2015 11 years ago
Jan 6, 2015 11 years ago
Dec 29, 2014 11 years ago

These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.

B- grade

Security

Fieldmanager 1.6.3 · audited by WP Registry

Medium-severity findings.

3 medium
Audited release
1.6.3
Findings
3
Worst severity
medium
Content hash
f4e935d8034e31452d72bf8a…

Findings

  • medium Post autocomplete AJAX discloses non-public post titles by ID or URL

    information_disclosure

    Fieldmanager_Datasource_Post::get_items() is the backend for wp_ajax_{fm_datasource_post_* } (registered when a Fieldmanager_Autocomplete uses this datasource; use_ajax defaults true). autocomplete_search() only calls check_ajax_referer('fm_search_nonce') — there is no current_user_can('read_post') / edit_post. Title LIKE search uses get_posts() with default post_status=publish, but a numeric fragment or http(s) URL takes a separate path: intval / parse_str / fm_url_to_post_id then get_post($id). That lookup ignores post_status and capability. Default query_args post_type is the string 'any', and the first branch is `'any' == $post_args['post_type']`, so every post type (posts, pages, attachments, custom types, even revisions if IDs hit them) is eligible. A Contributor or Author who can open post-new.php (where fm_add_script localizes fm_search.nonce) can POST fm_autocomplete_search=1,2,3… or an wp-admin URL with ?post= and receive JSON {label: <title>, value: <id>} for drafts, private, pending, and trash posts they cannot read in wp-admin. Action names are crc32 of the datasource config and are stable for default query_args. POST fm_context/fm_subcontext is copied into fm_calculate_context so the field (and thus the ajax action) is constructed on the AJAX request itself.

    php/datasource/class-fieldmanager-datasource-post.php:136-174

    Recommendation

    After get_post(), skip the row unless current_user_can('read_post', $post_id) (and/or the post is publicly viewable). Do not treat datasource post_type 'any' as a bypass of status. Apply the same read_post filter to the get_posts() result list. Keep the nonce and also require a capability consistent with the field context (edit_posts at minimum).

  • medium User autocomplete AJAX lists all users without list_users

    information_disclosure

    Fieldmanager_Datasource_User documents public $capability = 'list_users' and enforces it in presave() so a low-priv user cannot store a user reference. get_items() (used by autocomplete_search over wp_ajax_fm_datasource_user_*) never checks that capability. With default query_args it calls get_users(['search' => '*'.$fragment.'*']). Core's user search columns include user_email, user_login, user_nicename, and display_name, so a fragment of an email is an existence oracle, and a short fragment returns the site's user directory. JSON is {label: display_name (or user_email if the developer set display_property), value: ID} including accounts that have never published — those users are omitted from the public REST users collection. The only gate is fm_search_nonce, which is localized onto any admin screen that constructs Fieldmanager_Autocomplete, including profile.php (Subscriber-reachable) when the site registers user-context autocomplete fields. Same fm_context POST construction as the post datasource.

    php/datasource/class-fieldmanager-datasource-user.php:167-186

    Recommendation

    In autocomplete_search or get_items(), require current_user_can( $this->capability ) (default list_users) before calling get_users(). Restrict search_columns so user_email is not searchable unless the requester can list_users. Do not return users the current user cannot edit/list.

  • medium Quick Edit AJAX renders any post's Fieldmanager meta with no nonce or edit_post check

    information_disclosure

    wp_ajax_fm_quickedit_render → Fieldmanager_Context_QuickEdit::render_ajax_form() is registered from the Quick Edit constructor, which runs only when fm_match_context('quickedit') is true. fieldmanager.php treats GET action=fm_quickedit_render on admin-ajax.php as context quickedit / $_GET['post_type'], so a logged-in Subscriber request both constructs the field (via do_action('fm_quickedit_{type}'), the hook sites must use for Quick Edit to work at all) and then fires the ajax callback. The callback checks that column_name matches the field name and post_id is non-zero, then load()s post meta and echoes the full field HTML. There is no wp_verify_nonce / check_ajax_referer and no current_user_can('edit_post', $post_id). Observable: GET /wp-admin/admin-ajax.php?action=fm_quickedit_render&column_name={fm_name}&post_id={id}&post_type={type} as any authenticated user dumps that post's Fieldmanager values (private notes, related IDs, etc.). js/fieldmanager-quickedit.js inserts the response with jQuery.replaceWith; field templates escape values on output so this is disclosure, not XSS.

    php/context/class-fieldmanager-context-quickedit.php:170-199

    Recommendation

    Call check_ajax_referer and current_user_can('edit_post', $post_id) (or the post type's edit_post meta cap) before load()/render. Reject users who cannot access edit.php for that type. Bind the nonce to post_id.

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.