peass-ng/PEASS-ng · error · ArgumentException

Can not serialize non-public type

Error message

Can not serialize non-public type {0}.

What it means

ObjectMemberAccessor's private constructor builds a reflection-based accessor for a type. The check that rejects non-public types is commented out in this vendored copy, so under the original logic ArgumentException('Can not serialize non-public type {0}.') fires when the constructor is given an internal/private type for YAML serialization. The snippet shown is the source region where that guard would execute.

Solutions

  1. Make the type public (or the relevant members public) so the serializer can reflect it.
  2. Use [YamlSerializable]-compatible public DTOs as an intermediary and map from internal types.
  3. If you control the vendored serializer, note the guard is commented out — non-public types now pass through but may fail later on member access.
  4. Add InternalsVisibleTo if the serializer runs in a friend assembly context.

Example fix

// before
internal class Config { public string Name; } // serializer may reject
// after
public class Config { public string Name; }
Defensive patterns

Strategy: type-guard

Validate before calling

if (type != null && !type.IsPublic && !type.IsNestedPublic) throw new ArgumentException(type.FullName + " must be public for YAML serialization");

Type guard

static bool IsYamlSerializable(Type t) => t.IsPublic || t.IsNestedPublic;

Try / catch

try { serializer.Serialize(writer, obj); } catch (ArgumentException ex) when (ex.Message.Contains("non-public")) { mapToPublicDtoAndRetry(); }

Prevention

When it happens

Trigger: Constructing an ObjectMemberAccessor (via the YAML serializer) for a type not visible to the serializer — internal/private classes, or public types in unsigned assemblies without InternalsVisibleTo being reflected over.

Common situations: Serializing internal config/model classes; types marked internal in libraries; generic types instantiated with internal type arguments.

Related errors


AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02). Data as JSON: /api/errors/1aa37df415775da8. Report an issue: GitHub.

Appendix: source

Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/YamlSerializer/ObjectMemberAccessor.cs:46

        /// 指定した型へのアクセス方法を表すインスタンスを返す
        /// キャッシュに存在すればそれを返す
        /// キャッシュに存在しなければ新しく作って返す
        /// 作った物はキャッシュされる
        /// </summary>
        /// <param name="type">クラスまたは構造体を表す型情報</param>
        /// <returns></returns>
        public static ObjectMemberAccessor FindFor(Type type)
        {
            if ( !MemberAccessors.ContainsKey(type) )
                MemberAccessors[type] = new ObjectMemberAccessor(type);
            return MemberAccessors[type];
        }

        private ObjectMemberAccessor(Type type)
        {
            /*
            if ( !TypeUtils.IsPublic(type) )
                throw new ArgumentException(
                    "Can not serialize non-public type {0}.".DoFormat(type.FullName));
            */ 

            // public properties
            foreach ( var p in type.GetProperties(
                    System.Reflection.BindingFlags.Instance | 
                    System.Reflection.BindingFlags.Public | 
                    System.Reflection.BindingFlags.GetProperty) ) {
                var prop = p; // create closures with this local variable
                // not readable or parameters required to access the property
                if ( !prop.CanRead || prop.GetGetMethod(false) == null || prop.GetIndexParameters().Count() != 0 )
                    continue;
                Func<object, object> get = obj => prop.GetValue(obj, EmptyObjectArray);
                Action<object, object> set = null;
                if ( prop.CanWrite && prop.GetSetMethod(false) != null )
                    set = (obj, value) => prop.SetValue(obj, value, EmptyObjectArray);
                RegisterMember(type, prop, prop.PropertyType, get, set);
            }

View on GitHub (pinned to 53fb989abc)